File ovmf-bsc1186151-fix-iscsi-overflows.patch of Package ovmf.28635
From 4bf343fe11b54d36fdaa7596450ef06e0847a30a Mon Sep 17 00:00:00 2001
From: Sean Brogan <sean.brogan@microsoft.com>
Date: Mon, 24 Apr 2017 16:37:20 -0700
Subject: [PATCH 01/18] MdePkg/BaseSafeIntLib: Add SafeIntLib class and
instance
https://bugzilla.tianocore.org/show_bug.cgi?id=798
SafeIntLib provides helper functions to prevent integer overflow
during type conversion, addition, subtraction, and multiplication.
Conversion Functions
====================
* Converting from a signed type to an unsigned type of the same
size, or vice-versa.
* Converting to a smaller type that could possibly overflow.
* Converting from a signed type to a larger unsigned type.
Unsigned Addition, Subtraction, Multiplication
===============================================
* Unsigned integer math functions protect from overflow and
underflow (in case of subtraction).
Signed Addition, Subtraction, Multiplication
============================================
* Strongly consider using unsigned numbers.
* Signed numbers are often used where unsigned numbers should
be used. For example file sizes and array indices should always
be unsigned. Subtracting a larger positive signed number from a
smaller positive signed number with SafeInt32Sub() will succeed,
producing a negative number, that then must not be used as an
array index (but can occasionally be used as a pointer index.)
Similarly for adding a larger magnitude negative number to a
smaller magnitude positive number.
* SafeIntLib does not protect you from such errors. It tells you
if your integer operations overflowed, not if you are doing the
right thing with your non-overflowed integers.
* Likewise you can overflow a buffer with a non-overflowed
unsigned index.
Based on content from the following branch/commits:
https://github.com/Microsoft/MS_UEFI/tree/share/MsCapsuleSupport
https://github.com/Microsoft/MS_UEFI/commit/21ef3a321c907b40fa93797619c9f6c686dd92e0
https://github.com/Microsoft/MS_UEFI/commit/ca516b1a61315c2d823f453e12d2135098f53d61
https://github.com/Microsoft/MS_UEFI/commit/33bab4031a417d7d5a7d356c15a14c2e60302b2d
Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Sean Brogan <sean.brogan@microsoft.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
(cherry picked from commit d7a09cb86a0416c099fa3a9e0fbe2c8f399b28de)
---
MdePkg/Include/AArch64/ProcessorBind.h | 7 +-
MdePkg/Include/Arm/ProcessorBind.h | 7 +-
MdePkg/Include/Base.h | 8 +
MdePkg/Include/Ebc/ProcessorBind.h | 17 +-
MdePkg/Include/Ia32/ProcessorBind.h | 5 +
MdePkg/Include/Ipf/ProcessorBind.h | 7 +-
MdePkg/Include/Library/SafeIntLib.h | 3030 ++++++++++++
MdePkg/Include/X64/ProcessorBind.h | 5 +
.../Library/BaseSafeIntLib/BaseSafeIntLib.inf | 58 +
MdePkg/Library/BaseSafeIntLib/SafeIntLib.c | 4098 +++++++++++++++++
MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c | 554 +++
MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c | 508 ++
MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c | 614 +++
MdePkg/MdePkg.dec | 5 +
MdePkg/MdePkg.dsc | 1 +
15 files changed, 8915 insertions(+), 9 deletions(-)
create mode 100644 MdePkg/Include/Library/SafeIntLib.h
create mode 100644 MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
create mode 100644 MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
create mode 100644 MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c
create mode 100644 MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c
create mode 100644 MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c
diff --git a/MdePkg/Include/AArch64/ProcessorBind.h b/MdePkg/Include/AArch64/ProcessorBind.h
index 775e7498c5c9..d9caee598eaa 100644
--- a/MdePkg/Include/AArch64/ProcessorBind.h
+++ b/MdePkg/Include/AArch64/ProcessorBind.h
@@ -1,7 +1,7 @@
/** @file
Processor or Compiler specific defines and types for AArch64.
- Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
@@ -99,6 +99,11 @@ typedef INT64 INTN;
#define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL)
#define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL)
+///
+/// Minimum legal AArch64 INTN value.
+///
+#define MIN_INTN (((INTN)-9223372036854775807LL) - 1)
+
///
/// The stack alignment required for AARCH64
///
diff --git a/MdePkg/Include/Arm/ProcessorBind.h b/MdePkg/Include/Arm/ProcessorBind.h
index dde1fd1152ba..a0c16491ecde 100644
--- a/MdePkg/Include/Arm/ProcessorBind.h
+++ b/MdePkg/Include/Arm/ProcessorBind.h
@@ -1,7 +1,7 @@
/** @file
Processor or Compiler specific defines and types for ARM.
- Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -105,6 +105,11 @@ typedef INT32 INTN;
#define MAX_INTN ((INTN)0x7FFFFFFF)
#define MAX_UINTN ((UINTN)0xFFFFFFFF)
+///
+/// Minimum legal ARM INTN value.
+///
+#define MIN_INTN (((INTN)-2147483647) - 1)
+
///
/// The stack alignment required for ARM
///
diff --git a/MdePkg/Include/Base.h b/MdePkg/Include/Base.h
index 52252e7dc500..1efa78485e24 100644
--- a/MdePkg/Include/Base.h
+++ b/MdePkg/Include/Base.h
@@ -376,6 +376,14 @@ struct _LIST_ENTRY {
#define MAX_INT64 ((INT64)0x7FFFFFFFFFFFFFFFULL)
#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL)
+///
+/// Minimum values for the signed UEFI Data Types
+///
+#define MIN_INT8 (((INT8) -127) - 1)
+#define MIN_INT16 (((INT16) -32767) - 1)
+#define MIN_INT32 (((INT32) -2147483647) - 1)
+#define MIN_INT64 (((INT64) -9223372036854775807LL) - 1)
+
#define BIT0 0x00000001
#define BIT1 0x00000002
#define BIT2 0x00000004
diff --git a/MdePkg/Include/Ebc/ProcessorBind.h b/MdePkg/Include/Ebc/ProcessorBind.h
index da8b1a6d802a..ed4164891328 100644
--- a/MdePkg/Include/Ebc/ProcessorBind.h
+++ b/MdePkg/Include/Ebc/ProcessorBind.h
@@ -4,7 +4,7 @@
We currently only have one EBC compiler so there may be some Intel compiler
specific functions in this file.
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
@@ -91,23 +91,28 @@ typedef unsigned long UINTN;
/// A value of native width with the highest bit set.
/// Scalable macro to set the most significant bit in a natural number.
///
-#define MAX_BIT (1ULL << (sizeof (INTN) * 8 - 1))
+#define MAX_BIT ((UINTN)((1ULL << (sizeof (INTN) * 8 - 1))))
///
/// A value of native width with the two highest bits set.
/// Scalable macro to set the most 2 significant bits in a natural number.
///
-#define MAX_2_BITS (3ULL << (sizeof (INTN) * 8 - 2))
+#define MAX_2_BITS ((UINTN)(3ULL << (sizeof (INTN) * 8 - 2)))
///
/// Maximum legal EBC address
///
-#define MAX_ADDRESS ((UINTN) ~0)
+#define MAX_ADDRESS ((UINTN)(~0ULL >> (64 - sizeof (INTN) * 8)))
///
/// Maximum legal EBC INTN and UINTN values.
///
-#define MAX_UINTN ((UINTN) ~0)
-#define MAX_INTN ((INTN)~MAX_BIT)
+#define MAX_UINTN ((UINTN)(~0ULL >> (64 - sizeof (INTN) * 8)))
+#define MAX_INTN ((INTN)(~0ULL >> (65 - sizeof (INTN) * 8)))
+
+///
+/// Minimum legal EBC INTN value.
+///
+#define MIN_INTN (((INTN)-MAX_INTN) - 1)
///
/// The stack alignment required for EBC
diff --git a/MdePkg/Include/Ia32/ProcessorBind.h b/MdePkg/Include/Ia32/ProcessorBind.h
index 8ba2348261a2..6b723eba3de0 100644
--- a/MdePkg/Include/Ia32/ProcessorBind.h
+++ b/MdePkg/Include/Ia32/ProcessorBind.h
@@ -252,6 +252,11 @@ typedef INT32 INTN;
#define MAX_INTN ((INTN)0x7FFFFFFF)
#define MAX_UINTN ((UINTN)0xFFFFFFFF)
+///
+/// Minimum legal IA-32 INTN value.
+///
+#define MIN_INTN (((INTN)-2147483647) - 1)
+
///
/// The stack alignment required for IA-32.
///
diff --git a/MdePkg/Include/Ipf/ProcessorBind.h b/MdePkg/Include/Ipf/ProcessorBind.h
index 51885ca61359..bfbae01abb84 100644
--- a/MdePkg/Include/Ipf/ProcessorBind.h
+++ b/MdePkg/Include/Ipf/ProcessorBind.h
@@ -1,7 +1,7 @@
/** @file
Processor or Compiler specific defines and types for Intel Itanium(TM) processors.
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
@@ -242,6 +242,11 @@ typedef INT64 INTN;
#define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL)
#define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL)
+///
+/// Minimum legal Itanium-based INTN value.
+///
+#define MIN_INTN (((INTN)-9223372036854775807LL) - 1)
+
///
/// Per the Itanium Software Conventions and Runtime Architecture Guide,
/// section 3.3.4, IPF stack must always be 16-byte aligned.
diff --git a/MdePkg/Include/Library/SafeIntLib.h b/MdePkg/Include/Library/SafeIntLib.h
new file mode 100644
index 000000000000..583930195a61
--- /dev/null
+++ b/MdePkg/Include/Library/SafeIntLib.h
@@ -0,0 +1,3030 @@
+/** @file
+ This library provides helper functions to prevent integer overflow during
+ type conversion, addition, subtraction, and multiplication.
+
+ Copyright (c) 2017, Microsoft Corporation
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef __INT_SAFE_LIB_H__
+#define __INT_SAFE_LIB_H__
+
+//
+// It is common for -1 to be used as an error value
+//
+#define INT8_ERROR ((INT8) -1)
+#define UINT8_ERROR MAX_UINT8
+#define CHAR8_ERROR ((CHAR8)(MAX_INT8))
+#define INT16_ERROR ((INT16) -1)
+#define UINT16_ERROR MAX_UINT16
+#define CHAR16_ERROR MAX_UINT16
+#define INT32_ERROR ((INT32) -1)
+#define UINT32_ERROR MAX_UINT32
+#define INT64_ERROR ((INT64) -1)
+#define UINT64_ERROR MAX_UINT64
+#define INTN_ERROR ((INTN) -1)
+#define UINTN_ERROR MAX_UINTN
+
+//
+// CHAR16 is defined to be the same as UINT16, so for CHAR16
+// operations redirect to the UINT16 ones:
+//
+#define SafeInt8ToChar16 SafeInt8ToUint16
+#define SafeInt16ToChar16 SafeInt16ToUint16
+#define SafeInt32ToChar16 SafeInt32ToUint16
+#define SafeUint32ToChar16 SafeUint32ToUint16
+#define SafeInt64ToChar16 SafeInt64ToUint16
+#define SafeUint64ToChar16 SafeUint64ToUint16
+#define SafeIntnToChar16 SafeIntnToUint16
+#define SafeUintnToChar16 SafeUintnToUint16
+
+#define SafeChar16ToInt8 SafeUint16ToInt8
+#define SafeChar16ToUint8 SafeUint16ToUint8
+#define SafeChar16ToChar8 SafeUint16ToChar8
+#define SafeChar16ToInt16 SafeUint16ToInt16
+
+#define SafeChar16Mult SafeUint16Mult
+#define SafeChar16Sub SafeUint16Sub
+#define SafeChar16Add SafeUint16Add
+
+//
+// Conversion functions
+//
+// There are three reasons for having conversion functions:
+//
+// 1. We are converting from a signed type to an unsigned type of the same
+// size, or vice-versa.
+//
+// 2. We are converting to a smaller type, and we could therefore possibly
+// overflow.
+//
+// 3. We are converting to a bigger type, and we are signed and the type we are
+// converting to is unsigned.
+//
+
+/**
+ INT8 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUint8 (
+ IN INT8 Operand,
+ OUT UINT8 *Result
+ );
+
+/**
+ INT8 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToChar8 (
+ IN INT8 Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ INT8 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUint16 (
+ IN INT8 Operand,
+ OUT UINT16 *Result
+ );
+
+/**
+ INT8 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUint32 (
+ IN INT8 Operand,
+ OUT UINT32 *Result
+ );
+
+/**
+ INT8 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUintn (
+ IN INT8 Operand,
+ OUT UINTN *Result
+ );
+
+/**
+ INT8 -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUint64 (
+ IN INT8 Operand,
+ OUT UINT64 *Result
+ );
+
+/**
+ UINT8 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8ToInt8 (
+ IN UINT8 Operand,
+ OUT INT8 *Result
+ );
+
+/**
+ UINT8 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8ToChar8 (
+ IN UINT8 Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ INT16 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToInt8 (
+ IN INT16 Operand,
+ OUT INT8 *Result
+ );
+
+/**
+ INT16 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToChar8 (
+ IN INT16 Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ INT16 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUint8 (
+ IN INT16 Operand,
+ OUT UINT8 *pui8Result
+ );
+
+/**
+ INT16 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUint16 (
+ IN INT16 Operand,
+ OUT UINT16 *Result
+ );
+
+/**
+ INT16 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUint32 (
+ IN INT16 Operand,
+ OUT UINT32 *Result
+ );
+
+/**
+ INT16 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUintn (
+ IN INT16 Operand,
+ OUT UINTN *Result
+ );
+
+/**
+ INT16 -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUint64 (
+ IN INT16 Operand,
+ OUT UINT64 *Result
+ );
+
+/**
+ UINT16 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16ToInt8 (
+ IN UINT16 Operand,
+ OUT INT8 *Result
+ );
+
+/**
+ UINT16 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16ToChar8 (
+ IN UINT16 Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ UINT16 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16ToUint8 (
+ IN UINT16 Operand,
+ OUT UINT8 *pui8Result
+ );
+
+/**
+ UINT16 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16ToInt16 (
+ IN UINT16 Operand,
+ OUT INT16 *Result
+ );
+
+/**
+ INT32 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToInt8 (
+ IN INT32 Operand,
+ OUT INT8 *Result
+ );
+
+/**
+ INT32 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToChar8 (
+ IN INT32 Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ INT32 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUint8 (
+ IN INT32 Operand,
+ OUT UINT8 *pui8Result
+ );
+
+/**
+ INT32 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToInt16 (
+ IN INT32 Operand,
+ OUT INT16 *Result
+ );
+
+/**
+ INT32 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUint16 (
+ IN INT32 Operand,
+ OUT UINT16 *Result
+ );
+
+
+/**
+ INT32 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUint32 (
+ IN INT32 Operand,
+ OUT UINT32 *Result
+ );
+
+/**
+ INT32 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUintn (
+ IN INT32 Operand,
+ OUT UINTN *Result
+ );
+
+/**
+ INT32 -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUint64 (
+ IN INT32 Operand,
+ OUT UINT64 *Result
+ );
+
+/**
+ UINT32 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToInt8 (
+ IN UINT32 Operand,
+ OUT INT8 *Result
+ );
+
+/**
+ UINT32 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToChar8 (
+ IN UINT32 Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ UINT32 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToUint8 (
+ IN UINT32 Operand,
+ OUT UINT8 *pui8Result
+ );
+
+/**
+ UINT32 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToInt16 (
+ IN UINT32 Operand,
+ OUT INT16 *Result
+ );
+
+/**
+ UINT32 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToUint16 (
+ IN UINT32 Operand,
+ OUT UINT16 *Result
+ );
+
+/**
+ UINT32 -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToInt32 (
+ IN UINT32 Operand,
+ OUT INT32 *Result
+ );
+
+/**
+ UINT32 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToIntn (
+ IN UINT32 Operand,
+ OUT INTN *Result
+ );
+
+/**
+ INTN -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToInt8 (
+ IN INTN Operand,
+ OUT INT8 *Result
+ );
+
+/**
+ INTN -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToChar8 (
+ IN INTN Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ INTN -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint8 (
+ IN INTN Operand,
+ OUT UINT8 *pui8Result
+ );
+
+/**
+ INTN -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToInt16 (
+ IN INTN Operand,
+ OUT INT16 *Result
+ );
+
+/**
+ INTN -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint16 (
+ IN INTN Operand,
+ OUT UINT16 *Result
+ );
+
+/**
+ INTN -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToInt32 (
+ IN INTN Operand,
+ OUT INT32 *Result
+ );
+
+/**
+ INTN -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint32 (
+ IN INTN Operand,
+ OUT UINT32 *Result
+ );
+
+/**
+ INTN -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUintn (
+ IN INTN Operand,
+ OUT UINTN *Result
+ );
+
+/**
+ INTN -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint64 (
+ IN INTN Operand,
+ OUT UINT64 *Result
+ );
+
+/**
+ UINTN -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt8 (
+ IN UINTN Operand,
+ OUT INT8 *Result
+ );
+
+/**
+ UINTN -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToChar8 (
+ IN UINTN Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ UINTN -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToUint8 (
+ IN UINTN Operand,
+ OUT UINT8 *pui8Result
+ );
+
+/**
+ UINTN -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt16 (
+ IN UINTN Operand,
+ OUT INT16 *Result
+ );
+
+/**
+ UINTN -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToUint16 (
+ IN UINTN Operand,
+ OUT UINT16 *Result
+ );
+
+/**
+ UINTN -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt32 (
+ IN UINTN Operand,
+ OUT INT32 *Result
+ );
+
+/**
+ UINTN -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToUint32 (
+ IN UINTN Operand,
+ OUT UINT32 *Result
+ );
+
+/**
+ UINTN -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToIntn (
+ IN UINTN Operand,
+ OUT INTN *Result
+ );
+
+/**
+ UINTN -> INT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt64 (
+ IN UINTN Operand,
+ OUT INT64 *Result
+ );
+
+/**
+ INT64 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToInt8 (
+ IN INT64 Operand,
+ OUT INT8 *Result
+ );
+
+/**
+ INT64 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToChar8 (
+ IN INT64 Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ INT64 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUint8 (
+ IN INT64 Operand,
+ OUT UINT8 *Result
+ );
+
+/**
+ INT64 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToInt16 (
+ IN INT64 Operand,
+ OUT INT16 *Result
+ );
+
+/**
+ INT64 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUint16 (
+ IN INT64 Operand,
+ OUT UINT16 *Result
+ );
+
+/**
+ INT64 -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToInt32 (
+ IN INT64 Operand,
+ OUT INT32 *Result
+ );
+
+/**
+ INT64 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUint32 (
+ IN INT64 Operand,
+ OUT UINT32 *Result
+ );
+
+/**
+ INT64 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToIntn (
+ IN INT64 Operand,
+ OUT INTN *Result
+ );
+
+/**
+ INT64 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUintn (
+ IN INT64 Operand,
+ OUT UINTN *Result
+ );
+
+/**
+ INT64 -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUint64 (
+ IN INT64 Operand,
+ OUT UINT64 *Result
+ );
+
+/**
+ UINT64 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToInt8 (
+ IN UINT64 Operand,
+ OUT INT8 *Result
+ );
+
+/**
+ UINT64 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToChar8 (
+ IN UINT64 Operand,
+ OUT CHAR8 *Result
+ );
+
+/**
+ UINT64 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUint8 (
+ IN UINT64 Operand,
+ OUT UINT8 *Result
+ );
+
+/**
+ UINT64 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToInt16 (
+ IN UINT64 Operand,
+ OUT INT16 *Result
+ );
+
+/**
+ UINT64 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUint16 (
+ IN UINT64 Operand,
+ OUT UINT16 *Result
+ );
+
+/**
+ UINT64 -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToInt32 (
+ IN UINT64 Operand,
+ OUT INT32 *Result
+ );
+
+/**
+ UINT64 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUint32 (
+ IN UINT64 Operand,
+ OUT UINT32 *Result
+ );
+
+/**
+ UINT64 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToIntn (
+ IN UINT64 Operand,
+ OUT INTN *Result
+ );
+
+/**
+ UINT64 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUintn (
+ IN UINT64 Operand,
+ OUT UINTN *Result
+ );
+
+/**
+ UINT64 -> INT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToInt64 (
+ IN UINT64 Operand,
+ OUT INT64 *Result
+ );
+
+//
+// Addition functions
+//
+
+/**
+ UINT8 addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8Add (
+ IN UINT8 Augend,
+ IN UINT8 Addend,
+ OUT UINT8 *Result
+ );
+
+/**
+ UINT16 addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16Add (
+ IN UINT16 Augend,
+ IN UINT16 Addend,
+ OUT UINT16 *Result
+ );
+
+/**
+ UINT32 addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32Add (
+ IN UINT32 Augend,
+ IN UINT32 Addend,
+ OUT UINT32 *Result
+ );
+
+/**
+ UINTN addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnAdd (
+ IN UINTN Augend,
+ IN UINTN Addend,
+ OUT UINTN *Result
+ );
+
+/**
+ UINT64 addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64Add (
+ IN UINT64 Augend,
+ IN UINT64 Addend,
+ OUT UINT64 *Result
+ );
+
+//
+// Subtraction functions
+//
+
+/**
+ UINT8 subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8Sub (
+ IN UINT8 Minuend,
+ IN UINT8 Subtrahend,
+ OUT UINT8 *Result
+ );
+
+/**
+ UINT16 subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16Sub (
+ IN UINT16 Minuend,
+ IN UINT16 Subtrahend,
+ OUT UINT16 *Result
+ );
+
+/**
+ UINT32 subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32Sub (
+ IN UINT32 Minuend,
+ IN UINT32 Subtrahend,
+ OUT UINT32 *Result
+ );
+
+/**
+ UINTN subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnSub (
+ IN UINTN Minuend,
+ IN UINTN Subtrahend,
+ OUT UINTN *Result
+ );
+
+/**
+ UINT64 subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64Sub (
+ IN UINT64 Minuend,
+ IN UINT64 Subtrahend,
+ OUT UINT64 *Result
+ );
+
+//
+// Multiplication functions
+//
+
+/**
+ UINT8 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8Mult (
+ IN UINT8 Multiplicand,
+ IN UINT8 Multiplier,
+ OUT UINT8 *Result
+ );
+
+/**
+ UINT16 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16Mult (
+ IN UINT16 Multiplicand,
+ IN UINT16 Multiplier,
+ OUT UINT16 *Result
+ );
+
+/**
+ UINT32 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32Mult (
+ IN UINT32 Multiplicand,
+ IN UINT32 Multiplier,
+ OUT UINT32 *Result
+ );
+
+/**
+ UINTN multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnMult (
+ IN UINTN Multiplicand,
+ IN UINTN Multiplier,
+ OUT UINTN *Result
+ );
+
+/**
+ UINT64 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64Mult (
+ IN UINT64 Multiplicand,
+ IN UINT64 Multiplier,
+ OUT UINT64 *Result
+ );
+
+//
+// Signed operations
+//
+// Strongly consider using unsigned numbers.
+//
+// Signed numbers are often used where unsigned numbers should be used.
+// For example file sizes and array indices should always be unsigned.
+// Subtracting a larger positive signed number from a smaller positive
+// signed number with SafeInt32Sub will succeed, producing a negative number,
+// that then must not be used as an array index (but can occasionally be
+// used as a pointer index.) Similarly for adding a larger magnitude
+// negative number to a smaller magnitude positive number.
+//
+// This library does not protect you from such errors. It tells you if your
+// integer operations overflowed, not if you are doing the right thing
+// with your non-overflowed integers.
+//
+// Likewise you can overflow a buffer with a non-overflowed unsigned index.
+//
+
+//
+// Signed addition functions
+//
+
+/**
+ INT8 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8Add (
+ IN INT8 Augend,
+ IN INT8 Addend,
+ OUT INT8 *Result
+ );
+
+/**
+ CHAR8 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeChar8Add (
+ IN CHAR8 Augend,
+ IN CHAR8 Addend,
+ OUT CHAR8 *Result
+ );
+
+/**
+ INT16 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16Add (
+ IN INT16 Augend,
+ IN INT16 Addend,
+ OUT INT16 *Result
+ );
+
+/**
+ INT32 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32Add (
+ IN INT32 Augend,
+ IN INT32 Addend,
+ OUT INT32 *Result
+ );
+
+/**
+ INTN Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnAdd (
+ IN INTN Augend,
+ IN INTN Addend,
+ OUT INTN *Result
+ );
+
+/**
+ INT64 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64Add (
+ IN INT64 Augend,
+ IN INT64 Addend,
+ OUT INT64 *Result
+ );
+
+//
+// Signed subtraction functions
+//
+
+/**
+ INT8 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8Sub (
+ IN INT8 Minuend,
+ IN INT8 Subtrahend,
+ OUT INT8 *Result
+ );
+
+/**
+ CHAR8 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeChar8Sub (
+ IN CHAR8 Minuend,
+ IN CHAR8 Subtrahend,
+ OUT CHAR8 *Result
+ );
+
+/**
+ INT16 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16Sub (
+ IN INT16 Minuend,
+ IN INT16 Subtrahend,
+ OUT INT16 *Result
+ );
+
+/**
+ INT32 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32Sub (
+ IN INT32 Minuend,
+ IN INT32 Subtrahend,
+ OUT INT32 *Result
+ );
+
+/**
+ INTN Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnSub (
+ IN INTN Minuend,
+ IN INTN Subtrahend,
+ OUT INTN *Result
+ );
+
+/**
+ INT64 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64Sub (
+ IN INT64 Minuend,
+ IN INT64 Subtrahend,
+ OUT INT64 *Result
+ );
+
+//
+// Signed multiplication functions
+//
+
+/**
+ INT8 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8Mult (
+ IN INT8 Multiplicand,
+ IN INT8 Multiplier,
+ OUT INT8 *Result
+ );
+
+/**
+ CHAR8 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeChar8Mult (
+ IN CHAR8 Multiplicand,
+ IN CHAR8 Multiplier,
+ OUT CHAR8 *Result
+ );
+
+/**
+ INT16 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16Mult (
+ IN INT16 Multiplicand,
+ IN INT16 Multiplier,
+ OUT INT16 *Result
+ );
+
+/**
+ INT32 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32Mult (
+ IN INT32 Multiplicand,
+ IN INT32 Multiplier,
+ OUT INT32 *Result
+ );
+
+/**
+ INTN multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnMult (
+ IN INTN Multiplicand,
+ IN INTN Multiplier,
+ OUT INTN *Result
+ );
+
+/**
+ INT64 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64Mult (
+ IN INT64 Multiplicand,
+ IN INT64 Multiplier,
+ OUT INT64 *Result
+ );
+
+#endif // __INT_SAFE_LIB_H__
diff --git a/MdePkg/Include/X64/ProcessorBind.h b/MdePkg/Include/X64/ProcessorBind.h
index 72cc85151cba..de793b321586 100644
--- a/MdePkg/Include/X64/ProcessorBind.h
+++ b/MdePkg/Include/X64/ProcessorBind.h
@@ -266,6 +266,11 @@ typedef INT64 INTN;
#define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL)
#define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL)
+///
+/// Minimum legal x64 INTN value.
+///
+#define MIN_INTN (((INTN)-9223372036854775807LL) - 1)
+
///
/// The stack alignment required for x64
///
diff --git a/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf b/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
new file mode 100644
index 000000000000..20a83ed97bca
--- /dev/null
+++ b/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
@@ -0,0 +1,58 @@
+## @file
+# Safe Integer Library
+#
+# This library provides helper functions to prevent integer overflow during
+# type conversion, addition, subtraction, and multiplication.
+#
+# Copyright (c) 2017, Microsoft Corporation
+#
+# All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseSafeIntLib
+ FILE_GUID = 4EA91BFA-3482-4930-B136-70679C6CE489
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SafeIntLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SafeIntLib.c
+
+[Sources.Ia32, Sources.ARM]
+ SafeIntLib32.c
+
+[Sources.X64, Sources.IPF, Sources.AARCH64]
+ SafeIntLib64.c
+
+[Sources.EBC]
+ SafeIntLibEbc.c
+
+[Packages]
+ MdePkg/MdePkg.dec
diff --git a/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
new file mode 100644
index 000000000000..d846160ba0d1
--- /dev/null
+++ b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
@@ -0,0 +1,4098 @@
+/** @file
+ This library provides helper functions to prevent integer overflow during
+ type conversion, addition, subtraction, and multiplication.
+
+ Copyright (c) 2017, Microsoft Corporation
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Base.h>
+#include <Library/SafeIntLib.h>
+
+
+//
+// Magnitude of MIN_INT64 as expressed by a UINT64 number.
+//
+#define MIN_INT64_MAGNITUDE ((((UINT64) - (MIN_INT64 + 1))) + 1)
+
+//
+// Conversion functions
+//
+// There are three reasons for having conversion functions:
+//
+// 1. We are converting from a signed type to an unsigned type of the same
+// size, or vice-versa.
+//
+// 2. We are converting to a smaller type, and we could therefore possibly
+// overflow.
+//
+// 3. We are converting to a bigger type, and we are signed and the type we are
+// converting to is unsigned.
+//
+
+/**
+ INT8 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUint8 (
+ IN INT8 Operand,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT8 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToChar8 (
+ IN INT8 Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (CHAR8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT8 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUint16 (
+ IN INT8 Operand,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT8 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUint32 (
+ IN INT8 Operand,
+ OUT UINT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT8 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUintn (
+ IN INT8 Operand,
+ OUT UINTN *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINTN)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINTN_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT8 -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8ToUint64 (
+ IN INT8 Operand,
+ OUT UINT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT64)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT8 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8ToInt8 (
+ IN UINT8 Operand,
+ OUT INT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT8 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8ToChar8 (
+ IN UINT8 Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (CHAR8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT16 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToInt8 (
+ IN INT16 Operand,
+ OUT INT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= MIN_INT8) && (Operand <= MAX_INT8)) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT16 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToChar8 (
+ IN INT16 Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_INT8)) {
+ *Result = (CHAR8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT16 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUint8 (
+ IN INT16 Operand,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_UINT8)) {
+ *Result = (UINT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT16 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUint16 (
+ IN INT16 Operand,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT16 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUint32 (
+ IN INT16 Operand,
+ OUT UINT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT16 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUintn (
+ IN INT16 Operand,
+ OUT UINTN *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINTN)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINTN_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT16 -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16ToUint64 (
+ IN INT16 Operand,
+ OUT UINT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT64)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT16 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16ToInt8 (
+ IN UINT16 Operand,
+ OUT INT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT16 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16ToChar8 (
+ IN UINT16 Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT16 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16ToUint8 (
+ IN UINT16 Operand,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_UINT8) {
+ *Result = (UINT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT16 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16ToInt16 (
+ IN UINT16 Operand,
+ OUT INT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT16) {
+ *Result = (INT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT32 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToInt8 (
+ IN INT32 Operand,
+ OUT INT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= MIN_INT8) && (Operand <= MAX_INT8)) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT32 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToChar8 (
+ IN INT32 Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_INT8)) {
+ *Result = (CHAR8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT32 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUint8 (
+ IN INT32 Operand,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_UINT8)) {
+ *Result = (UINT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT32 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToInt16 (
+ IN INT32 Operand,
+ OUT INT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= MIN_INT16) && (Operand <= MAX_INT16)) {
+ *Result = (INT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT32 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUint16 (
+ IN INT32 Operand,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_UINT16)) {
+ *Result = (UINT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT32 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUint32 (
+ IN INT32 Operand,
+ OUT UINT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT32 -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUint64 (
+ IN INT32 Operand,
+ OUT UINT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT64)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT32 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToInt8 (
+ IN UINT32 Operand,
+ OUT INT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT32 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToChar8 (
+ IN UINT32 Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT32 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToUint8 (
+ IN UINT32 Operand,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_UINT8) {
+ *Result = (UINT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT32 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToInt16 (
+ IN UINT32 Operand,
+ OUT INT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT16) {
+ *Result = (INT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT32 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToUint16 (
+ IN UINT32 Operand,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_UINT16) {
+ *Result = (UINT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT32 -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToInt32 (
+ IN UINT32 Operand,
+ OUT INT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT32) {
+ *Result = (INT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INTN -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToInt8 (
+ IN INTN Operand,
+ OUT INT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= MIN_INT8) && (Operand <= MAX_INT8)) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INTN -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToChar8 (
+ IN INTN Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_INT8)) {
+ *Result = (CHAR8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INTN -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint8 (
+ IN INTN Operand,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_UINT8)) {
+ *Result = (UINT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INTN -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToInt16 (
+ IN INTN Operand,
+ OUT INT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= MIN_INT16) && (Operand <= MAX_INT16)) {
+ *Result = (INT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INTN -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint16 (
+ IN INTN Operand,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_UINT16)) {
+ *Result = (UINT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INTN -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUintn (
+ IN INTN Operand,
+ OUT UINTN *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINTN)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINTN_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INTN -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint64 (
+ IN INTN Operand,
+ OUT UINT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT64)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt8 (
+ IN UINTN Operand,
+ OUT INT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToChar8 (
+ IN UINTN Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToUint8 (
+ IN UINTN Operand,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_UINT8) {
+ *Result = (UINT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt16 (
+ IN UINTN Operand,
+ OUT INT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT16) {
+ *Result = (INT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToUint16 (
+ IN UINTN Operand,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_UINT16) {
+ *Result = (UINT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt32 (
+ IN UINTN Operand,
+ OUT INT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT32) {
+ *Result = (INT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToIntn (
+ IN UINTN Operand,
+ OUT INTN *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INTN) {
+ *Result = (INTN)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INTN_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT64 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToInt8 (
+ IN INT64 Operand,
+ OUT INT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= MIN_INT8) && (Operand <= MAX_INT8)) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT64 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToChar8 (
+ IN INT64 Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_INT8)) {
+ *Result = (CHAR8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT64 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUint8 (
+ IN INT64 Operand,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_UINT8)) {
+ *Result = (UINT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT64 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToInt16 (
+ IN INT64 Operand,
+ OUT INT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= MIN_INT16) && (Operand <= MAX_INT16)) {
+ *Result = (INT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT64 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUint16 (
+ IN INT64 Operand,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_UINT16)) {
+ *Result = (UINT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT64 -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToInt32 (
+ IN INT64 Operand,
+ OUT INT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= MIN_INT32) && (Operand <= MAX_INT32)) {
+ *Result = (INT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT64 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUint32 (
+ IN INT64 Operand,
+ OUT UINT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Operand >= 0) && (Operand <= MAX_UINT32)) {
+ *Result = (UINT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ INT64 -> UINT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUint64 (
+ IN INT64 Operand,
+ OUT UINT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT64)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 -> INT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToInt8 (
+ IN UINT64 Operand,
+ OUT INT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 -> CHAR8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToChar8 (
+ IN UINT64 Operand,
+ OUT CHAR8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT8) {
+ *Result = (INT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = CHAR8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 -> UINT8 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUint8 (
+ IN UINT64 Operand,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_UINT8) {
+ *Result = (UINT8)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 -> INT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToInt16 (
+ IN UINT64 Operand,
+ OUT INT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT16) {
+ *Result = (INT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 -> UINT16 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUint16 (
+ IN UINT64 Operand,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_UINT16) {
+ *Result = (UINT16)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToInt32 (
+ IN UINT64 Operand,
+ OUT INT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT32) {
+ *Result = (INT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUint32 (
+ IN UINT64 Operand,
+ OUT UINT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_UINT32) {
+ *Result = (UINT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToIntn (
+ IN UINT64 Operand,
+ OUT INTN *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INTN) {
+ *Result = (INTN)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INTN_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 -> INT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToInt64 (
+ IN UINT64 Operand,
+ OUT INT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand <= MAX_INT64) {
+ *Result = (INT64)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = INT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+//
+// Addition functions
+//
+
+/**
+ UINT8 addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8Add (
+ IN UINT8 Augend,
+ IN UINT8 Addend,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (((UINT8)(Augend + Addend)) >= Augend) {
+ *Result = (UINT8)(Augend + Addend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT16 addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16Add (
+ IN UINT16 Augend,
+ IN UINT16 Addend,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (((UINT16)(Augend + Addend)) >= Augend) {
+ *Result = (UINT16)(Augend + Addend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT32 addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32Add (
+ IN UINT32 Augend,
+ IN UINT32 Addend,
+ OUT UINT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Augend + Addend) >= Augend) {
+ *Result = (Augend + Addend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64Add (
+ IN UINT64 Augend,
+ IN UINT64 Addend,
+ OUT UINT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Augend + Addend) >= Augend) {
+ *Result = (Augend + Addend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+//
+// Subtraction functions
+//
+
+/**
+ UINT8 subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8Sub (
+ IN UINT8 Minuend,
+ IN UINT8 Subtrahend,
+ OUT UINT8 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Minuend >= Subtrahend) {
+ *Result = (UINT8)(Minuend - Subtrahend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT8_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT16 subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16Sub (
+ IN UINT16 Minuend,
+ IN UINT16 Subtrahend,
+ OUT UINT16 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Minuend >= Subtrahend) {
+ *Result = (UINT16)(Minuend - Subtrahend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT16_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT32 subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32Sub (
+ IN UINT32 Minuend,
+ IN UINT32 Subtrahend,
+ OUT UINT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Minuend >= Subtrahend) {
+ *Result = (Minuend - Subtrahend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINT64 subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64Sub (
+ IN UINT64 Minuend,
+ IN UINT64 Subtrahend,
+ OUT UINT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Minuend >= Subtrahend) {
+ *Result = (Minuend - Subtrahend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+//
+// Multiplication functions
+//
+
+/**
+ UINT8 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint8Mult (
+ IN UINT8 Multiplicand,
+ IN UINT8 Multiplier,
+ OUT UINT8 *Result
+ )
+{
+ UINT32 IntermediateResult;
+
+ IntermediateResult = ((UINT32)Multiplicand) *((UINT32)Multiplier);
+
+ return SafeUint32ToUint8 (IntermediateResult, Result);
+}
+
+/**
+ UINT16 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint16Mult (
+ IN UINT16 Multiplicand,
+ IN UINT16 Multiplier,
+ OUT UINT16 *Result
+ )
+{
+ UINT32 IntermediateResult;
+
+ IntermediateResult = ((UINT32)Multiplicand) *((UINT32)Multiplier);
+
+ return SafeUint32ToUint16 (IntermediateResult, Result);
+}
+
+/**
+ UINT32 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32Mult (
+ IN UINT32 Multiplicand,
+ IN UINT32 Multiplier,
+ OUT UINT32 *Result
+ )
+{
+ UINT64 IntermediateResult;
+
+ IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier);
+
+ return SafeUint64ToUint32 (IntermediateResult, Result);
+}
+
+/**
+ UINT64 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64Mult (
+ IN UINT64 Multiplicand,
+ IN UINT64 Multiplier,
+ OUT UINT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+ UINT32 DwordA;
+ UINT32 DwordB;
+ UINT32 DwordC;
+ UINT32 DwordD;
+ UINT64 ProductAD;
+ UINT64 ProductBC;
+ UINT64 ProductBD;
+ UINT64 UnsignedResult;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ ProductAD = 0;
+ ProductBC = 0;
+ ProductBD = 0;
+ UnsignedResult = 0;
+ Status = RETURN_BUFFER_TOO_SMALL;
+
+ //
+ // 64x64 into 128 is like 32.32 x 32.32.
+ //
+ // a.b * c.d = a*(c.d) + .b*(c.d) = a*c + a*.d + .b*c + .b*.d
+ // back in non-decimal notation where A=a*2^32 and C=c*2^32:
+ // A*C + A*d + b*C + b*d
+ // So there are four components to add together.
+ // result = (a*c*2^64) + (a*d*2^32) + (b*c*2^32) + (b*d)
+ //
+ // a * c must be 0 or there would be bits in the high 64-bits
+ // a * d must be less than 2^32 or there would be bits in the high 64-bits
+ // b * c must be less than 2^32 or there would be bits in the high 64-bits
+ // then there must be no overflow of the resulting values summed up.
+ //
+ DwordA = (UINT32)(Multiplicand >> 32);
+ DwordC = (UINT32)(Multiplier >> 32);
+
+ //
+ // common case -- if high dwords are both zero, no chance for overflow
+ //
+ if ((DwordA == 0) && (DwordC == 0)) {
+ DwordB = (UINT32)Multiplicand;
+ DwordD = (UINT32)Multiplier;
+
+ *Result = (((UINT64)DwordB) *(UINT64)DwordD);
+ Status = RETURN_SUCCESS;
+ } else {
+ //
+ // a * c must be 0 or there would be bits set in the high 64-bits
+ //
+ if ((DwordA == 0) ||
+ (DwordC == 0)) {
+ DwordD = (UINT32)Multiplier;
+
+ //
+ // a * d must be less than 2^32 or there would be bits set in the high 64-bits
+ //
+ ProductAD = (((UINT64)DwordA) *(UINT64)DwordD);
+ if ((ProductAD & 0xffffffff00000000) == 0) {
+ DwordB = (UINT32)Multiplicand;
+
+ //
+ // b * c must be less than 2^32 or there would be bits set in the high 64-bits
+ //
+ ProductBC = (((UINT64)DwordB) *(UINT64)DwordC);
+ if ((ProductBC & 0xffffffff00000000) == 0) {
+ //
+ // now sum them all up checking for overflow.
+ // shifting is safe because we already checked for overflow above
+ //
+ if (!RETURN_ERROR (SafeUint64Add (ProductBC << 32, ProductAD << 32, &UnsignedResult))) {
+ //
+ // b * d
+ //
+ ProductBD = (((UINT64)DwordB) *(UINT64)DwordD);
+
+ if (!RETURN_ERROR (SafeUint64Add (UnsignedResult, ProductBD, &UnsignedResult))) {
+ *Result = UnsignedResult;
+ Status = RETURN_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (RETURN_ERROR (Status)) {
+ *Result = UINT64_ERROR;
+ }
+ return Status;
+}
+
+//
+// Signed operations
+//
+// Strongly consider using unsigned numbers.
+//
+// Signed numbers are often used where unsigned numbers should be used.
+// For example file sizes and array indices should always be unsigned.
+// Subtracting a larger positive signed number from a smaller positive
+// signed number with SafeInt32Sub will succeed, producing a negative number,
+// that then must not be used as an array index (but can occasionally be
+// used as a pointer index.) Similarly for adding a larger magnitude
+// negative number to a smaller magnitude positive number.
+//
+// This library does not protect you from such errors. It tells you if your
+// integer operations overflowed, not if you are doing the right thing
+// with your non-overflowed integers.
+//
+// Likewise you can overflow a buffer with a non-overflowed unsigned index.
+//
+
+//
+// Signed addition functions
+//
+
+/**
+ INT8 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8Add (
+ IN INT8 Augend,
+ IN INT8 Addend,
+ OUT INT8 *Result
+ )
+{
+ return SafeInt32ToInt8 (((INT32)Augend) + ((INT32)Addend), Result);
+}
+
+/**
+ CHAR8 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeChar8Add (
+ IN CHAR8 Augend,
+ IN CHAR8 Addend,
+ OUT CHAR8 *Result
+ )
+{
+ INT32 Augend32;
+ INT32 Addend32;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ Augend32 = (INT32)Augend;
+ Addend32 = (INT32)Addend;
+ if (Augend32 < 0 || Augend32 > MAX_INT8) {
+ *Result = CHAR8_ERROR;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+ if (Addend32 < 0 || Addend32 > MAX_INT8) {
+ *Result = CHAR8_ERROR;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return SafeInt32ToChar8 (Augend32 + Addend32, Result);
+}
+
+/**
+ INT16 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16Add (
+ IN INT16 Augend,
+ IN INT16 Addend,
+ OUT INT16 *Result
+ )
+{
+ return SafeInt32ToInt16 (((INT32)Augend) + ((INT32)Addend), Result);
+}
+
+/**
+ INT32 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32Add (
+ IN INT32 Augend,
+ IN INT32 Addend,
+ OUT INT32 *Result
+ )
+{
+ return SafeInt64ToInt32 (((INT64)Augend) + ((INT64)Addend), Result);
+}
+
+/**
+ INT64 Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64Add (
+ IN INT64 Augend,
+ IN INT64 Addend,
+ OUT INT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+ INT64 SignedResult;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ SignedResult = Augend + Addend;
+
+ //
+ // Adding positive to negative never overflows.
+ // If you add two positive numbers, you expect a positive result.
+ // If you add two negative numbers, you expect a negative result.
+ // Overflow if inputs are the same sign and output is not that sign.
+ //
+ if (((Augend < 0) == (Addend < 0)) &&
+ ((Augend < 0) != (SignedResult < 0))) {
+ *Result = INT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ } else {
+ *Result = SignedResult;
+ Status = RETURN_SUCCESS;
+ }
+
+ return Status;
+}
+
+//
+// Signed subtraction functions
+//
+
+/**
+ INT8 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8Sub (
+ IN INT8 Minuend,
+ IN INT8 Subtrahend,
+ OUT INT8 *Result
+ )
+{
+ return SafeInt32ToInt8 (((INT32)Minuend) - ((INT32)Subtrahend), Result);
+}
+
+/**
+ CHAR8 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeChar8Sub (
+ IN CHAR8 Minuend,
+ IN CHAR8 Subtrahend,
+ OUT CHAR8 *Result
+ )
+{
+ INT32 Minuend32;
+ INT32 Subtrahend32;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ Minuend32 = (INT32)Minuend;
+ Subtrahend32 = (INT32)Subtrahend;
+ if (Minuend32 < 0 || Minuend32 > MAX_INT8) {
+ *Result = CHAR8_ERROR;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+ if (Subtrahend32 < 0 || Subtrahend32 > MAX_INT8) {
+ *Result = CHAR8_ERROR;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return SafeInt32ToChar8 (Minuend32 - Subtrahend32, Result);
+}
+
+/**
+ INT16 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16Sub (
+ IN INT16 Minuend,
+ IN INT16 Subtrahend,
+ OUT INT16 *Result
+ )
+{
+ return SafeInt32ToInt16 (((INT32)Minuend) - ((INT32)Subtrahend), Result);
+}
+
+/**
+ INT32 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32Sub (
+ IN INT32 Minuend,
+ IN INT32 Subtrahend,
+ OUT INT32 *Result
+ )
+{
+ return SafeInt64ToInt32 (((INT64)Minuend) - ((INT64)Subtrahend), Result);
+}
+
+/**
+ INT64 Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64Sub (
+ IN INT64 Minuend,
+ IN INT64 Subtrahend,
+ OUT INT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+ INT64 SignedResult;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ SignedResult = Minuend - Subtrahend;
+
+ //
+ // Subtracting a positive number from a positive number never overflows.
+ // Subtracting a negative number from a negative number never overflows.
+ // If you subtract a negative number from a positive number, you expect a positive result.
+ // If you subtract a positive number from a negative number, you expect a negative result.
+ // Overflow if inputs vary in sign and the output does not have the same sign as the first input.
+ //
+ if (((Minuend < 0) != (Subtrahend < 0)) &&
+ ((Minuend < 0) != (SignedResult < 0))) {
+ *Result = INT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ } else {
+ *Result = SignedResult;
+ Status = RETURN_SUCCESS;
+ }
+
+ return Status;
+}
+
+//
+// Signed multiplication functions
+//
+
+/**
+ INT8 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt8Mult (
+ IN INT8 Multiplicand,
+ IN INT8 Multiplier,
+ OUT INT8 *Result
+ )
+{
+ return SafeInt32ToInt8 (((INT32)Multiplier) *((INT32)Multiplicand), Result);
+}
+
+/**
+ CHAR8 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeChar8Mult (
+ IN CHAR8 Multiplicand,
+ IN CHAR8 Multiplier,
+ OUT CHAR8 *Result
+ )
+{
+ INT32 Multiplicand32;
+ INT32 Multiplier32;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ Multiplicand32 = (INT32)Multiplicand;
+ Multiplier32 = (INT32)Multiplier;
+ if (Multiplicand32 < 0 || Multiplicand32 > MAX_INT8) {
+ *Result = CHAR8_ERROR;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+ if (Multiplier32 < 0 || Multiplier32 > MAX_INT8) {
+ *Result = CHAR8_ERROR;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return SafeInt32ToChar8 (Multiplicand32 * Multiplier32, Result);
+}
+
+/**
+ INT16 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt16Mult (
+ IN INT16 Multiplicand,
+ IN INT16 Multiplier,
+ OUT INT16 *Result
+ )
+{
+ return SafeInt32ToInt16 (((INT32)Multiplicand) *((INT32)Multiplier), Result);
+}
+
+/**
+ INT32 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32Mult (
+ IN INT32 Multiplicand,
+ IN INT32 Multiplier,
+ OUT INT32 *Result
+ )
+{
+ return SafeInt64ToInt32 (((INT64)Multiplicand) *((INT64)Multiplier), Result);
+}
+
+/**
+ INT64 multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64Mult (
+ IN INT64 Multiplicand,
+ IN INT64 Multiplier,
+ OUT INT64 *Result
+ )
+{
+ RETURN_STATUS Status;
+ UINT64 UnsignedMultiplicand;
+ UINT64 UnsignedMultiplier;
+ UINT64 UnsignedResult;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ //
+ // Split into sign and magnitude, do unsigned operation, apply sign.
+ //
+ if (Multiplicand < 0) {
+ //
+ // Avoid negating the most negative number.
+ //
+ UnsignedMultiplicand = ((UINT64)(- (Multiplicand + 1))) + 1;
+ } else {
+ UnsignedMultiplicand = (UINT64)Multiplicand;
+ }
+
+ if (Multiplier < 0) {
+ //
+ // Avoid negating the most negative number.
+ //
+ UnsignedMultiplier = ((UINT64)(- (Multiplier + 1))) + 1;
+ } else {
+ UnsignedMultiplier = (UINT64)Multiplier;
+ }
+
+ Status = SafeUint64Mult (UnsignedMultiplicand, UnsignedMultiplier, &UnsignedResult);
+ if (!RETURN_ERROR (Status)) {
+ if ((Multiplicand < 0) != (Multiplier < 0)) {
+ if (UnsignedResult > MIN_INT64_MAGNITUDE) {
+ *Result = INT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ } else {
+ *Result = - ((INT64)UnsignedResult);
+ }
+ } else {
+ if (UnsignedResult > MAX_INT64) {
+ *Result = INT64_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ } else {
+ *Result = (INT64)UnsignedResult;
+ }
+ }
+ } else {
+ *Result = INT64_ERROR;
+ }
+ return Status;
+}
+
diff --git a/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c b/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c
new file mode 100644
index 000000000000..18bfb9e4130c
--- /dev/null
+++ b/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c
@@ -0,0 +1,554 @@
+/** @file
+ This library provides helper functions to prevent integer overflow during
+ type conversion, addition, subtraction, and multiplication.
+
+ Copyright (c) 2017, Microsoft Corporation
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Base.h>
+#include <Library/SafeIntLib.h>
+
+/**
+ INT32 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUintn (
+ IN INT32 Operand,
+ OUT UINTN *Result
+ )
+{
+ return SafeInt32ToUint32 (Operand, (UINT32 *)Result);
+}
+
+/**
+ UINT32 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToIntn (
+ IN UINT32 Operand,
+ OUT INTN *Result
+ )
+{
+ return SafeUint32ToInt32 (Operand, (INT32 *)Result);
+}
+
+/**
+ INTN -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToInt32 (
+ IN INTN Operand,
+ OUT INT32 *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *Result = (INT32)Operand;
+ return RETURN_SUCCESS;
+}
+
+/**
+ INTN -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint32 (
+ IN INTN Operand,
+ OUT UINT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Operand >= 0) {
+ *Result = (UINT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToUint32 (
+ IN UINTN Operand,
+ OUT UINT32 *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *Result = (UINT32)Operand;
+ return RETURN_SUCCESS;
+}
+
+/**
+ UINTN -> INT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt64 (
+ IN UINTN Operand,
+ OUT INT64 *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *Result = (INT64)Operand;
+ return RETURN_SUCCESS;
+}
+
+/**
+ INT64 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToIntn (
+ IN INT64 Operand,
+ OUT INTN *Result
+ )
+{
+ return SafeInt64ToInt32 (Operand, (INT32 *)Result);
+}
+
+/**
+ INT64 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUintn (
+ IN INT64 Operand,
+ OUT UINTN *Result
+ )
+{
+ return SafeInt64ToUint32 (Operand, (UINT32 *)Result);
+}
+
+/**
+ UINT64 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUintn (
+ IN UINT64 Operand,
+ OUT UINTN *Result
+ )
+{
+ return SafeUint64ToUint32 ((UINT64) Operand, (UINT32 *)Result);
+}
+
+/**
+ UINTN addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnAdd (
+ IN UINTN Augend,
+ IN UINTN Addend,
+ OUT UINTN *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((Augend + Addend) >= Augend) {
+ *Result = (Augend + Addend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINTN_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnSub (
+ IN UINTN Minuend,
+ IN UINTN Subtrahend,
+ OUT UINTN *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Minuend >= Subtrahend) {
+ *Result = (Minuend - Subtrahend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINTN_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+}
+
+/**
+ UINTN multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnMult (
+ IN UINTN Multiplicand,
+ IN UINTN Multiplier,
+ OUT UINTN *Result
+ )
+{
+ UINT64 IntermediateResult;
+
+ IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier);
+
+ return SafeUint64ToUintn (IntermediateResult, Result);
+}
+
+/**
+ INTN Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnAdd (
+ IN INTN Augend,
+ IN INTN Addend,
+ OUT INTN *Result
+ )
+{
+ return SafeInt64ToIntn (((INT64)Augend) + ((INT64)Addend), Result);
+}
+
+/**
+ INTN Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnSub (
+ IN INTN Minuend,
+ IN INTN Subtrahend,
+ OUT INTN *Result
+ )
+{
+ return SafeInt64ToIntn (((INT64)Minuend) - ((INT64)Subtrahend), Result);
+}
+
+/**
+ INTN multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnMult (
+ IN INTN Multiplicand,
+ IN INTN Multiplier,
+ OUT INTN *Result
+ )
+{
+ return SafeInt64ToIntn (((INT64)Multiplicand) *((INT64)Multiplier), Result);
+}
+
diff --git a/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c b/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c
new file mode 100644
index 000000000000..b423c5cc1bdc
--- /dev/null
+++ b/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c
@@ -0,0 +1,508 @@
+/** @file
+ This library provides helper functions to prevent integer overflow during
+ type conversion, addition, subtraction, and multiplication.
+
+ Copyright (c) 2017, Microsoft Corporation
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Base.h>
+#include <Library/SafeIntLib.h>
+
+/**
+ INT32 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUintn (
+ IN INT32 Operand,
+ OUT UINTN *Result
+ )
+{
+ return SafeInt32ToUint64 (Operand, (UINT64 *) Result);
+}
+
+/**
+ UINT32 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToIntn (
+ IN UINT32 Operand,
+ OUT INTN *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *Result = Operand;
+ return RETURN_SUCCESS;
+}
+
+/**
+ INTN -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToInt32 (
+ IN INTN Operand,
+ OUT INT32 *Result
+ )
+{
+ return SafeInt64ToInt32 ((INT64) Operand, Result);
+}
+
+/**
+ INTN -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint32 (
+ IN INTN Operand,
+ OUT UINT32 *Result
+ )
+{
+ return SafeInt64ToUint32 ((INT64)Operand, Result);
+}
+
+/**
+ UINTN -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToUint32 (
+ IN UINTN Operand,
+ OUT UINT32 *Result
+ )
+{
+ return SafeUint64ToUint32 ((UINT64)Operand, Result);
+}
+
+/**
+ UINTN -> INT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt64 (
+ IN UINTN Operand,
+ OUT INT64 *Result
+ )
+{
+ return SafeUint64ToInt64 ((UINT64)Operand, Result);
+}
+
+/**
+ INT64 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToIntn (
+ IN INT64 Operand,
+ OUT INTN *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *Result = (INTN)Operand;
+ return RETURN_SUCCESS;
+}
+
+/**
+ INT64 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUintn (
+ IN INT64 Operand,
+ OUT UINTN *Result
+ )
+{
+ return SafeInt64ToUint64 (Operand, (UINT64 *)Result);
+}
+
+/**
+ UINT64 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUintn (
+ IN UINT64 Operand,
+ OUT UINTN *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *Result = Operand;
+ return RETURN_SUCCESS;
+}
+
+/**
+ UINTN addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnAdd (
+ IN UINTN Augend,
+ IN UINTN Addend,
+ OUT UINTN *Result
+ )
+{
+ return SafeUint64Add ((UINT64)Augend, (UINT64)Addend, (UINT64 *)Result);
+}
+
+/**
+ UINTN subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnSub (
+ IN UINTN Minuend,
+ IN UINTN Subtrahend,
+ OUT UINTN *Result
+ )
+{
+ return SafeUint64Sub ((UINT64)Minuend, (UINT64)Subtrahend, (UINT64 *)Result);
+}
+
+/**
+ UINTN multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnMult (
+ IN UINTN Multiplicand,
+ IN UINTN Multiplier,
+ OUT UINTN *Result
+ )
+{
+ return SafeUint64Mult ((UINT64)Multiplicand, (UINT64)Multiplier, (UINT64 *)Result);
+}
+
+/**
+ INTN Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnAdd (
+ IN INTN Augend,
+ IN INTN Addend,
+ OUT INTN *Result
+ )
+{
+ return SafeInt64Add ((INT64)Augend, (INT64)Addend, (INT64 *)Result);
+}
+
+/**
+ INTN Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnSub (
+ IN INTN Minuend,
+ IN INTN Subtrahend,
+ OUT INTN *Result
+ )
+{
+ return SafeInt64Sub ((INT64)Minuend, (INT64)Subtrahend, (INT64 *)Result);
+}
+
+/**
+ INTN multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnMult (
+ IN INTN Multiplicand,
+ IN INTN Multiplier,
+ OUT INTN *Result
+ )
+{
+ return SafeInt64Mult ((INT64)Multiplicand, (INT64)Multiplier, (INT64 *)Result);
+}
+
diff --git a/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c b/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c
new file mode 100644
index 000000000000..4478957b7e33
--- /dev/null
+++ b/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c
@@ -0,0 +1,614 @@
+/** @file
+ This library provides helper functions to prevent integer overflow during
+ type conversion, addition, subtraction, and multiplication.
+
+ Copyright (c) 2017, Microsoft Corporation
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <Base.h>
+#include <Library/SafeIntLib.h>
+
+/**
+ INT32 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt32ToUintn (
+ IN INT32 Operand,
+ OUT UINTN *Result
+ )
+{
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ return SafeInt32ToUint32 (Operand, (UINT32 *)Result);
+ }
+ return SafeInt32ToUint64 (Operand, (UINT64 *) Result);
+}
+
+/**
+ UINT32 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint32ToIntn (
+ IN UINT32 Operand,
+ OUT INTN *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ return SafeUint32ToInt32 (Operand, (INT32 *)Result);
+ }
+ *Result = Operand;
+ return RETURN_SUCCESS;
+}
+
+/**
+ INTN -> INT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToInt32 (
+ IN INTN Operand,
+ OUT INT32 *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ *Result = (INT32)Operand;
+ return RETURN_SUCCESS;
+ }
+ return SafeInt64ToInt32 ((INT64) Operand, Result);
+}
+
+/**
+ INTN -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnToUint32 (
+ IN INTN Operand,
+ OUT UINT32 *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ if (Operand >= 0) {
+ *Result = (UINT32)Operand;
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINT32_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+ }
+ return SafeInt64ToUint32 ((INT64)Operand, Result);
+}
+
+/**
+ UINTN -> UINT32 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToUint32 (
+ IN UINTN Operand,
+ OUT UINT32 *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ *Result = (UINT32)Operand;
+ return RETURN_SUCCESS;
+ }
+ return SafeUint64ToUint32 ((UINT64)Operand, Result);
+}
+
+/**
+ UINTN -> INT64 conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnToInt64 (
+ IN UINTN Operand,
+ OUT INT64 *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ *Result = (INT64)Operand;
+ return RETURN_SUCCESS;
+ }
+ return SafeUint64ToInt64 ((UINT64)Operand, Result);
+}
+
+/**
+ INT64 -> INTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToIntn (
+ IN INT64 Operand,
+ OUT INTN *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ return SafeInt64ToInt32 (Operand, (INT32 *)Result);
+ }
+ *Result = (INTN)Operand;
+ return RETURN_SUCCESS;
+}
+
+/**
+ INT64 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeInt64ToUintn (
+ IN INT64 Operand,
+ OUT UINTN *Result
+ )
+{
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ return SafeInt64ToUint32 (Operand, (UINT32 *)Result);
+ }
+ return SafeInt64ToUint64 (Operand, (UINT64 *)Result);
+}
+
+/**
+ UINT64 -> UINTN conversion
+
+ Converts the value specified by Operand to a value specified by Result type
+ and stores the converted value into the caller allocated output buffer
+ specified by Result. The caller must pass in a Result buffer that is at
+ least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the conversion results in an overflow or an underflow condition, then
+ Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Operand Operand to be converted to new type
+ @param[out] Result Pointer to the result of conversion
+
+ @retval RETURN_SUCCESS Successful conversion
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUint64ToUintn (
+ IN UINT64 Operand,
+ OUT UINTN *Result
+ )
+{
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ return SafeUint64ToUint32 ((UINT64) Operand, (UINT32 *)Result);
+ }
+ *Result = Operand;
+ return RETURN_SUCCESS;
+}
+
+/**
+ UINTN addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnAdd (
+ IN UINTN Augend,
+ IN UINTN Addend,
+ OUT UINTN *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ if ((UINT32)(Augend + Addend) >= Augend) {
+ *Result = (Augend + Addend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINTN_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+ }
+ return SafeUint64Add ((UINT64)Augend, (UINT64)Addend, (UINT64 *)Result);
+}
+
+/**
+ UINTN subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnSub (
+ IN UINTN Minuend,
+ IN UINTN Subtrahend,
+ OUT UINTN *Result
+ )
+{
+ RETURN_STATUS Status;
+
+ if (Result == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ if (Minuend >= Subtrahend) {
+ *Result = (Minuend - Subtrahend);
+ Status = RETURN_SUCCESS;
+ } else {
+ *Result = UINTN_ERROR;
+ Status = RETURN_BUFFER_TOO_SMALL;
+ }
+
+ return Status;
+ }
+ return SafeUint64Sub ((UINT64)Minuend, (UINT64)Subtrahend, (UINT64 *)Result);
+}
+
+/**
+ UINTN multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeUintnMult (
+ IN UINTN Multiplicand,
+ IN UINTN Multiplier,
+ OUT UINTN *Result
+ )
+{
+ UINT64 IntermediateResult;
+
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier);
+
+ return SafeUint64ToUintn (IntermediateResult, Result);
+ }
+ return SafeUint64Mult ((UINT64)Multiplicand, (UINT64)Multiplier, (UINT64 *)Result);
+}
+
+/**
+ INTN Addition
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Augend A number to which addend will be added
+ @param[in] Addend A number to be added to another
+ @param[out] Result Pointer to the result of addition
+
+ @retval RETURN_SUCCESS Successful addition
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnAdd (
+ IN INTN Augend,
+ IN INTN Addend,
+ OUT INTN *Result
+ )
+{
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ return SafeInt64ToIntn (((INT64)Augend) + ((INT64)Addend), Result);
+ }
+ return SafeInt64Add ((INT64)Augend, (INT64)Addend, (INT64 *)Result);
+}
+
+/**
+ INTN Subtraction
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Minuend A number from which another is to be subtracted.
+ @param[in] Subtrahend A number to be subtracted from another
+ @param[out] Result Pointer to the result of subtraction
+
+ @retval RETURN_SUCCESS Successful subtraction
+ @retval RETURN_BUFFER_TOO_SMALL Underflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnSub (
+ IN INTN Minuend,
+ IN INTN Subtrahend,
+ OUT INTN *Result
+ )
+{
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ return SafeInt64ToIntn (((INT64)Minuend) - ((INT64)Subtrahend), Result);
+ }
+ return SafeInt64Sub ((INT64)Minuend, (INT64)Subtrahend, (INT64 *)Result);
+}
+
+/**
+ INTN multiplication
+
+ Performs the requested operation using the input parameters into a value
+ specified by Result type and stores the converted value into the caller
+ allocated output buffer specified by Result. The caller must pass in a
+ Result buffer that is at least as large as the Result type.
+
+ If Result is NULL, RETURN_INVALID_PARAMETER is returned.
+
+ If the requested operation results in an overflow or an underflow condition,
+ then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
+
+ @param[in] Multiplicand A number that is to be multiplied by another
+ @param[in] Multiplier A number by which the multiplicand is to be multiplied
+ @param[out] Result Pointer to the result of multiplication
+
+ @retval RETURN_SUCCESS Successful multiplication
+ @retval RETURN_BUFFER_TOO_SMALL Overflow
+ @retval RETURN_INVALID_PARAMETER Result is NULL
+**/
+RETURN_STATUS
+EFIAPI
+SafeIntnMult (
+ IN INTN Multiplicand,
+ IN INTN Multiplier,
+ OUT INTN *Result
+ )
+{
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ return SafeInt64ToIntn (((INT64)Multiplicand) *((INT64)Multiplier), Result);
+ }
+ return SafeInt64Mult ((INT64)Multiplicand, (INT64)Multiplier, (INT64 *)Result);
+}
+
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 603e498676ec..b4239507c89f 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -241,6 +241,11 @@ [LibraryClasses]
## @libraryclass provides EFI_FILE_HANDLE services
FileHandleLib|Include/Library/FileHandleLib.h
+ ## @libraryclass provides helper functions to prevent integer overflow during
+ # type conversion, addition, subtraction, and multiplication.
+ ##
+ SafeIntLib|Include/Library/SafeIntLib.h
+
[LibraryClasses.IA32, LibraryClasses.X64]
## @libraryclass Abstracts both S/W SMI generation and detection.
##
diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
index 8f5726350e6c..9b992036c52d 100644
--- a/MdePkg/MdePkg.dsc
+++ b/MdePkg/MdePkg.dsc
@@ -86,6 +86,7 @@ [Components]
MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
+ MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
--
2.31.1
From 999d637156abdee7a6c10cafb054050f82a9f88d Mon Sep 17 00:00:00 2001
From: Liming Gao <liming.gao@intel.com>
Date: Wed, 31 Jan 2018 20:27:10 +0800
Subject: [PATCH 02/18] MdePkg SafeIntLib: Update API definition to use the
same output name
In SafeUintnToChar8(), update its output parameter name.
Update pui8Result --> Result to match its library implementation
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Liming Gao <liming.gao@intel.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 93efab6d9a8e2278631752fad934425de0a6337a)
---
MdePkg/Include/Library/SafeIntLib.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/MdePkg/Include/Library/SafeIntLib.h b/MdePkg/Include/Library/SafeIntLib.h
index 583930195a61..8c5003f67838 100644
--- a/MdePkg/Include/Library/SafeIntLib.h
+++ b/MdePkg/Include/Library/SafeIntLib.h
@@ -375,7 +375,7 @@ RETURN_STATUS
EFIAPI
SafeInt16ToUint8 (
IN INT16 Operand,
- OUT UINT8 *pui8Result
+ OUT UINT8 *Result
);
/**
@@ -564,7 +564,7 @@ RETURN_STATUS
EFIAPI
SafeUint16ToUint8 (
IN UINT16 Operand,
- OUT UINT8 *pui8Result
+ OUT UINT8 *Result
);
/**
@@ -672,7 +672,7 @@ RETURN_STATUS
EFIAPI
SafeInt32ToUint8 (
IN INT32 Operand,
- OUT UINT8 *pui8Result
+ OUT UINT8 *Result
);
/**
@@ -889,7 +889,7 @@ RETURN_STATUS
EFIAPI
SafeUint32ToUint8 (
IN UINT32 Operand,
- OUT UINT8 *pui8Result
+ OUT UINT8 *Result
);
/**
@@ -1078,7 +1078,7 @@ RETURN_STATUS
EFIAPI
SafeIntnToUint8 (
IN INTN Operand,
- OUT UINT8 *pui8Result
+ OUT UINT8 *Result
);
/**
@@ -1321,7 +1321,7 @@ RETURN_STATUS
EFIAPI
SafeUintnToUint8 (
IN UINTN Operand,
- OUT UINT8 *pui8Result
+ OUT UINT8 *Result
);
/**
--
2.31.1
From fa269ce1110c5905d9ea7ab6514868ea831d5b6d Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Thu, 15 Feb 2018 14:47:11 +0100
Subject: [PATCH 03/18] MdePkg/BaseSafeIntLib: fix undefined behavior in
SafeInt64Sub()
The subtraction in the assignment
SignedResult = Minuend - Subtrahend;
is performed with unchecked INT64 operands. According to ISO C, if the
mathematical result of signed integer subtraction cannot be represented in
the result type, the behavior is undefined. (Refer to ISO C99 6.5p5.
6.2.5p9 only exempts unsigned integers, and 6.3.1.3p3 does not apply
because it treats the conversion of integers that have been successfully
evaluated first.)
Replace the after-the-fact result checking with checks on the operands,
and only perform the subtraction if it is safe.
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Michael D Kinney <michael.d.kinney@intel.com>
(cherry picked from commit 54c7728a04658b09ea1a50b9e35e838fde166003)
---
MdePkg/Library/BaseSafeIntLib/SafeIntLib.c | 50 +++++++++++++++++-----
1 file changed, 39 insertions(+), 11 deletions(-)
diff --git a/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
index d846160ba0d1..8e857927b067 100644
--- a/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
+++ b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
@@ -3837,27 +3837,55 @@ SafeInt64Sub (
)
{
RETURN_STATUS Status;
- INT64 SignedResult;
if (Result == NULL) {
return RETURN_INVALID_PARAMETER;
}
- SignedResult = Minuend - Subtrahend;
-
//
- // Subtracting a positive number from a positive number never overflows.
- // Subtracting a negative number from a negative number never overflows.
- // If you subtract a negative number from a positive number, you expect a positive result.
- // If you subtract a positive number from a negative number, you expect a negative result.
- // Overflow if inputs vary in sign and the output does not have the same sign as the first input.
+ // * A Subtrahend of zero can never cause underflow or overflow.
//
- if (((Minuend < 0) != (Subtrahend < 0)) &&
- ((Minuend < 0) != (SignedResult < 0))) {
+ // * A positive Subtrahend can only cause underflow. The underflow condition
+ // is:
+ //
+ // (Minuend - Subtrahend) < MIN_INT64
+ //
+ // Adding Subtrahend to both sides yields
+ //
+ // Minuend < (MIN_INT64 + Subtrahend)
+ //
+ // This condition can be coded directly in C because the RHS will neither
+ // underflow nor overflow. That is due to the starting condition:
+ //
+ // 0 < Subtrahend <= MAX_INT64
+ //
+ // Adding MIN_INT64 to all three sides yields
+ //
+ // MIN_INT64 < (MIN_INT64 + Subtrahend) <= (MIN_INT64 + MAX_INT64) = -1
+ //
+ // * A negative Subtrahend can only cause overflow. The overflow condition is
+ //
+ // (Minuend - Subtrahend) > MAX_INT64
+ //
+ // Adding Subtrahend to both sides yields
+ //
+ // Minuend > (MAX_INT64 + Subtrahend)
+ //
+ // This condition can be coded directly in C because the RHS will neither
+ // underflow nor overflow. That is due to the starting condition:
+ //
+ // MIN_INT64 <= Subtrahend < 0
+ //
+ // Adding MAX_INT64 to all three sides yields
+ //
+ // -1 = (MAX_INT64 + MIN_INT64) <= (MAX_INT64 + Subtrahend) < MAX_INT64
+ //
+ if (((Subtrahend > 0) && (Minuend < (MIN_INT64 + Subtrahend))) ||
+ ((Subtrahend < 0) && (Minuend > (MAX_INT64 + Subtrahend)))) {
*Result = INT64_ERROR;
Status = RETURN_BUFFER_TOO_SMALL;
} else {
- *Result = SignedResult;
+ *Result = Minuend - Subtrahend;
Status = RETURN_SUCCESS;
}
--
2.31.1
From 6be6a23b1c39eb48c4649d4a5344efc697c80608 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Thu, 15 Feb 2018 14:47:11 +0100
Subject: [PATCH 04/18] MdePkg/BaseSafeIntLib: fix undefined behavior in
SafeInt64Add()
The addition in the assignment
SignedResult = Augend + Addend;
is performed with unchecked INT64 operands. According to ISO C, if the
mathematical result of signed integer addition cannot be represented in
the result type, the behavior is undefined. (Refer to ISO C99 6.5p5.
6.2.5p9 only exempts unsigned integers, and 6.3.1.3p3 does not apply
because it treats the conversion of integers that have been successfully
evaluated first.)
Replace the after-the-fact result checking with checks on the operands,
and only perform the addition if it is safe.
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Michael D Kinney <michael.d.kinney@intel.com>
(cherry picked from commit 41bfaffd13094d9042110091e6c37adf20c4032c)
---
MdePkg/Library/BaseSafeIntLib/SafeIntLib.c | 56 ++++++++++++++++++----
1 file changed, 46 insertions(+), 10 deletions(-)
diff --git a/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
index 8e857927b067..56d97cf65601 100644
--- a/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
+++ b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
@@ -3631,26 +3631,62 @@ SafeInt64Add (
)
{
RETURN_STATUS Status;
- INT64 SignedResult;
if (Result == NULL) {
return RETURN_INVALID_PARAMETER;
}
- SignedResult = Augend + Addend;
-
//
- // Adding positive to negative never overflows.
- // If you add two positive numbers, you expect a positive result.
- // If you add two negative numbers, you expect a negative result.
- // Overflow if inputs are the same sign and output is not that sign.
+ // * An Addend of zero can never cause underflow or overflow.
//
- if (((Augend < 0) == (Addend < 0)) &&
- ((Augend < 0) != (SignedResult < 0))) {
+ // * A positive Addend can only cause overflow. The overflow condition is
+ //
+ // (Augend + Addend) > MAX_INT64
+ //
+ // Subtracting Addend from both sides yields
+ //
+ // Augend > (MAX_INT64 - Addend)
+ //
+ // This condition can be coded directly in C because the RHS will neither
+ // underflow nor overflow. That is due to the starting condition:
+ //
+ // 0 < Addend <= MAX_INT64
+ //
+ // Multiplying all three sides by (-1) yields
+ //
+ // 0 > (-Addend) >= (-MAX_INT64)
+ //
+ // Adding MAX_INT64 to all three sides yields
+ //
+ // MAX_INT64 > (MAX_INT64 - Addend) >= 0
+ //
+ // * A negative Addend can only cause underflow. The underflow condition is
+ //
+ // (Augend + Addend) < MIN_INT64
+ //
+ // Subtracting Addend from both sides yields
+ //
+ // Augend < (MIN_INT64 - Addend)
+ //
+ // This condition can be coded directly in C because the RHS will neither
+ // underflow nor overflow. That is due to the starting condition:
+ //
+ // MIN_INT64 <= Addend < 0
+ //
+ // Multiplying all three sides by (-1) yields
+ //
+ // (-MIN_INT64) >= (-Addend) > 0
+ //
+ // Adding MIN_INT64 to all three sides yields
+ //
+ // 0 >= (MIN_INT64 - Addend) > MIN_INT64
+ //
+ if (((Addend > 0) && (Augend > (MAX_INT64 - Addend))) ||
+ ((Addend < 0) && (Augend < (MIN_INT64 - Addend)))) {
*Result = INT64_ERROR;
Status = RETURN_BUFFER_TOO_SMALL;
} else {
- *Result = SignedResult;
+ *Result = Augend + Addend;
Status = RETURN_SUCCESS;
}
--
2.31.1
From db10f161d3ecb393287a1b9ab51f5c842ca02eec Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Thu, 15 Feb 2018 17:09:43 +0100
Subject: [PATCH 05/18] MdePkg/BaseSafeIntLib: clean up parentheses in
MIN_INT64_MAGNITUDE
The definition of the MIN_INT64_MAGNITUDE macro is correct, but it's
harder to read than necessary: the sub-expression
(( (UINT64) - (MIN_INT64 + 1) ))
is doubly parenthesized. Reusing one pair of the outer parens, rewrite the
sub-expression (without change in meaning) so that the minus sign cannot
be mistaken for subtraction:
( (UINT64)(- (MIN_INT64 + 1)) )
The resultant macro definition matches the following expressions in
SafeInt64Mult():
> //
> // Avoid negating the most negative number.
> //
> UnsignedMultiplicand = ((UINT64)(- (Multiplicand + 1))) + 1;
and
> //
> // Avoid negating the most negative number.
> //
> UnsignedMultiplier = ((UINT64)(- (Multiplier + 1))) + 1;
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Michael D Kinney <michael.d.kinney@intel.com>
(cherry picked from commit 8c33cc0ec926b17396fcd71686c727b991984d4a)
---
MdePkg/Library/BaseSafeIntLib/SafeIntLib.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
index 56d97cf65601..de91ffeca2a5 100644
--- a/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
+++ b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
@@ -33,7 +33,7 @@
//
// Magnitude of MIN_INT64 as expressed by a UINT64 number.
//
-#define MIN_INT64_MAGNITUDE ((((UINT64) - (MIN_INT64 + 1))) + 1)
+#define MIN_INT64_MAGNITUDE (((UINT64)(- (MIN_INT64 + 1))) + 1)
//
// Conversion functions
--
2.31.1
From a22ebb786eaab51636df481243b08f5364961be2 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Thu, 15 Feb 2018 17:09:43 +0100
Subject: [PATCH 06/18] MdePkg/BaseSafeIntLib: fix undefined behavior in
SafeInt64Mult()
If we have to negate UnsignedResult (due to exactly one of Multiplicand
and Multiplier being negative), and UnsignedResult is exactly
MIN_INT64_MAGNITUDE (value 2^63), then the statement
*Result = - ((INT64)UnsignedResult);
invokes both implementation-defined behavior and undefined behavior.
First, MIN_INT64_MAGNITUDE is not representable as INT64, therefore the
result of the (inner) conversion
(INT64)MIN_INT64_MAGNITUDE
is implementation-defined, or an implementation-defined signal is raised,
according to ISO C99 6.3.1.3p3.
Second, if we assume that the C language implementation defines the
conversion to INT64 simply as reinterpreting the bit pattern
0x8000_0000_0000_0000 as a signed integer in two's complement
representation, then the conversion immediately produces the negative
value MIN_INT64 (value -(2^63)). In turn, the (outer) negation
-(MIN_INT64)
invokes undefined behavior, because the mathematical result of the
negation, namely 2^63, cannot be represented in an INT64 object. (Not even
mentioning the fact that the mathematical result would be incorrect.) In
practice, the undefined negation of MIN_INT64 happens to produce an
unchanged, valid-looking result on x86, i.e. (-(MIN_INT64)) == MIN_INT64.
We can summarize this as the undefined -- effectless -- negation canceling
out the botched -- auto-negating -- implementation-defined conversion.
Instead of relying on such behavior, dedicate a branch to this situation:
assign MIN_INT64 directly. The branch can be triggered e.g. by multiplying
(2^62) by (-2).
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Michael D Kinney <michael.d.kinney@intel.com>
(cherry picked from commit 75505d161133cbeb57185b567d7b05756d255a3f)
---
MdePkg/Library/BaseSafeIntLib/SafeIntLib.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
index de91ffeca2a5..c5f13d7e0828 100644
--- a/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
+++ b/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c
@@ -4143,6 +4143,8 @@ SafeInt64Mult (
if (UnsignedResult > MIN_INT64_MAGNITUDE) {
*Result = INT64_ERROR;
Status = RETURN_BUFFER_TOO_SMALL;
+ } else if (UnsignedResult == MIN_INT64_MAGNITUDE) {
+ *Result = MIN_INT64;
} else {
*Result = - ((INT64)UnsignedResult);
}
--
2.31.1
From 69b56bb6d1db05bb687bbda9d84ef1512d2d6bff Mon Sep 17 00:00:00 2001
From: Jiaxin Wu <jiaxin.wu@intel.com>
Date: Fri, 4 May 2018 11:48:43 +0800
Subject: [PATCH 07/18] NetworkPkg/NetworkPkg.dsc: Add the instance of library
class [SafeIntLib].
This patch is to add the instance of library class [SafeIntLib] to fix the
NetworkPkg build error, which is caused by the commit of 2167c7f7 that the
TlsLib will always consume SafeIntLib.
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Long Qin <qin.long@intel.com>
Cc: Bi Dandan <dandan.bi@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
Reviewed-by: Long Qin <qin.long@intel.com>
(cherry picked from commit e9b4a4625c35f74824f05a2d846977756f7dd2a0)
---
NetworkPkg/NetworkPkg.dsc | 1 +
1 file changed, 1 insertion(+)
diff --git a/NetworkPkg/NetworkPkg.dsc b/NetworkPkg/NetworkPkg.dsc
index b193f5f38bfd..bafcd4882d4a 100644
--- a/NetworkPkg/NetworkPkg.dsc
+++ b/NetworkPkg/NetworkPkg.dsc
@@ -45,6 +45,7 @@ [LibraryClasses]
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
--
2.31.1
From 43a81e1c770a67a23754b870a676866cc019269a Mon Sep 17 00:00:00 2001
From: Michael D Kinney <michael.d.kinney@intel.com>
Date: Fri, 29 Dec 2017 18:59:21 -0800
Subject: [PATCH 08/18] OvmfPkg: Add SafeIntLib and BmpSupportLib to DSC files
https://bugzilla.tianocore.org/show_bug.cgi?id=800
Based on content from the following branch/commits:
https://github.com/Microsoft/MS_UEFI/tree/share/MsCapsuleSupport
https://github.com/Microsoft/MS_UEFI/commit/33bab4031a417d7d5a7d356c15a14c2e60302b2d
https://github.com/Microsoft/MS_UEFI/commit/ca516b1a61315c2d823f453e12d2135098f53d61
https://github.com/Microsoft/MS_UEFI/commit/2b9f111f2e74a4c2ef4c4e32379e111f016dbd9b
The BootGraphicsResourceTableDxe module uses the BmpSupportLib
and SafeIntLib to convert a GOP BLT buffer to a BMP graphics image.
Add library mappings for these new library classes.
Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Bret Barkelew <Bret.Barkelew@microsoft.com>
(cherry picked from commit 7fc21c29e84b018898299e93cc2052fa5ad9bab0)
NOTE from Gary:
Remove importing of BmpSupportLib since we only need SafeIntLib for
bsc#1186151
---
OvmfPkg/OvmfPkgIa32.dsc | 1 +
OvmfPkg/OvmfPkgIa32X64.dsc | 1 +
OvmfPkg/OvmfPkgX64.dsc | 1 +
3 files changed, 3 insertions(+)
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 7ccb61147f27..bc124cb3eb17 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -102,6 +102,7 @@ [LibraryClasses]
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 237ec71b5ec0..c58bc2006ca7 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -107,6 +107,7 @@ [LibraryClasses]
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index a5047fa38e61..4317f122c7bd 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -107,6 +107,7 @@ [LibraryClasses]
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
--
2.31.1
From ffd772ee01d2294cb9f045640ef719708536a039 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 26 Apr 2021 19:05:20 +0200
Subject: [PATCH 09/18] NetworkPkg/IScsiDxe: wrap IScsiCHAP source files to 80
characters
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Working with overlong lines is difficult for me; rewrap the CHAP-related
source files in IScsiDxe to 80 characters width. No functional changes.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiCHAP.c | 90 +++++++++++++++++++++++++--------
NetworkPkg/IScsiDxe/IScsiCHAP.h | 3 +-
2 files changed, 71 insertions(+), 22 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.c b/NetworkPkg/IScsiDxe/IScsiCHAP.c
index 18c49b952f56..5f045b07851c 100644
--- a/NetworkPkg/IScsiDxe/IScsiCHAP.c
+++ b/NetworkPkg/IScsiDxe/IScsiCHAP.c
@@ -1,5 +1,6 @@
/** @file
- This file is for Challenge-Handshake Authentication Protocol (CHAP) Configuration.
+ This file is for Challenge-Handshake Authentication Protocol (CHAP)
+ Configuration.
Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
@@ -24,9 +25,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
@param[in] ChallengeLength The length of iSCSI CHAP challenge message.
@param[out] ChapResponse The calculation of the expected hash value.
- @retval EFI_SUCCESS The expected hash value was calculatedly successfully.
- @retval EFI_PROTOCOL_ERROR The length of the secret should be at least the
- length of the hash value for the hashing algorithm chosen.
+ @retval EFI_SUCCESS The expected hash value was calculatedly
+ successfully.
+ @retval EFI_PROTOCOL_ERROR The length of the secret should be at least
+ the length of the hash value for the hashing
+ algorithm chosen.
@retval EFI_PROTOCOL_ERROR MD5 hash operation fail.
@retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete MD5.
@@ -100,8 +103,10 @@ Exit:
@param[in] AuthData iSCSI CHAP authentication data.
@param[in] TargetResponse The response from target.
- @retval EFI_SUCCESS The response from target passed authentication.
- @retval EFI_SECURITY_VIOLATION The response from target was not expected value.
+ @retval EFI_SUCCESS The response from target passed
+ authentication.
+ @retval EFI_SECURITY_VIOLATION The response from target was not expected
+ value.
@retval Others Other errors as indicated.
**/
@@ -199,7 +204,10 @@ IScsiCHAPOnRspReceived (
//
// The first Login Response.
//
- Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_TARGET_PORTAL_GROUP_TAG);
+ Value = IScsiGetValueByKeyFromList (
+ KeyValueList,
+ ISCSI_KEY_TARGET_PORTAL_GROUP_TAG
+ );
if (Value == NULL) {
goto ON_EXIT;
}
@@ -211,13 +219,17 @@ IScsiCHAPOnRspReceived (
Session->TargetPortalGroupTag = (UINT16) Result;
- Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_AUTH_METHOD);
+ Value = IScsiGetValueByKeyFromList (
+ KeyValueList,
+ ISCSI_KEY_AUTH_METHOD
+ );
if (Value == NULL) {
goto ON_EXIT;
}
//
- // Initiator mandates CHAP authentication but target replies without "CHAP", or
- // initiator suggets "None" but target replies with some kind of auth method.
+ // Initiator mandates CHAP authentication but target replies without
+ // "CHAP", or initiator suggets "None" but target replies with some kind of
+ // auth method.
//
if (Session->AuthType == ISCSI_AUTH_TYPE_NONE) {
if (AsciiStrCmp (Value, ISCSI_KEY_VALUE_NONE) != 0) {
@@ -242,7 +254,10 @@ IScsiCHAPOnRspReceived (
//
// The Target replies with CHAP_A=<A> CHAP_I=<I> CHAP_C=<C>
//
- Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_ALGORITHM);
+ Value = IScsiGetValueByKeyFromList (
+ KeyValueList,
+ ISCSI_KEY_CHAP_ALGORITHM
+ );
if (Value == NULL) {
goto ON_EXIT;
}
@@ -255,12 +270,18 @@ IScsiCHAPOnRspReceived (
goto ON_EXIT;
}
- Identifier = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_IDENTIFIER);
+ Identifier = IScsiGetValueByKeyFromList (
+ KeyValueList,
+ ISCSI_KEY_CHAP_IDENTIFIER
+ );
if (Identifier == NULL) {
goto ON_EXIT;
}
- Challenge = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_CHALLENGE);
+ Challenge = IScsiGetValueByKeyFromList (
+ KeyValueList,
+ ISCSI_KEY_CHAP_CHALLENGE
+ );
if (Challenge == NULL) {
goto ON_EXIT;
}
@@ -275,7 +296,11 @@ IScsiCHAPOnRspReceived (
AuthData->InIdentifier = (UINT32) Result;
AuthData->InChallengeLength = ISCSI_CHAP_AUTH_MAX_LEN;
- IScsiHexToBin ((UINT8 *) AuthData->InChallenge, &AuthData->InChallengeLength, Challenge);
+ IScsiHexToBin (
+ (UINT8 *) AuthData->InChallenge,
+ &AuthData->InChallengeLength,
+ Challenge
+ );
Status = IScsiCHAPCalculateResponse (
AuthData->InIdentifier,
AuthData->AuthConfig->CHAPSecret,
@@ -309,7 +334,10 @@ IScsiCHAPOnRspReceived (
goto ON_EXIT;
}
- Response = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_RESPONSE);
+ Response = IScsiGetValueByKeyFromList (
+ KeyValueList,
+ ISCSI_KEY_CHAP_RESPONSE
+ );
if (Response == NULL) {
goto ON_EXIT;
}
@@ -347,7 +375,8 @@ ON_EXIT:
@param[in, out] Pdu The PDU to send out.
@retval EFI_SUCCESS All check passed and the phase-related CHAP
- authentication info is filled into the iSCSI PDU.
+ authentication info is filled into the iSCSI
+ PDU.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
@retval EFI_PROTOCOL_ERROR Some kind of protocol error occurred.
@@ -398,7 +427,11 @@ IScsiCHAPToSendReq (
// It's the initial Login Request. Fill in the key=value pairs mandatory
// for the initial Login Request.
//
- IScsiAddKeyValuePair (Pdu, ISCSI_KEY_INITIATOR_NAME, mPrivate->InitiatorName);
+ IScsiAddKeyValuePair (
+ Pdu,
+ ISCSI_KEY_INITIATOR_NAME,
+ mPrivate->InitiatorName
+ );
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_SESSION_TYPE, "Normal");
IScsiAddKeyValuePair (
Pdu,
@@ -419,7 +452,8 @@ IScsiCHAPToSendReq (
case ISCSI_CHAP_STEP_ONE:
//
- // First step, send the Login Request with CHAP_A=<A1,A2...> key-value pair.
+ // First step, send the Login Request with CHAP_A=<A1,A2...> key-value
+ // pair.
//
AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", ISCSI_CHAP_ALGORITHM_MD5);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_ALGORITHM, ValueStr);
@@ -435,11 +469,20 @@ IScsiCHAPToSendReq (
//
// CHAP_N=<N>
//
- IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (CHAR8 *) &AuthData->AuthConfig->CHAPName);
+ IScsiAddKeyValuePair (
+ Pdu,
+ ISCSI_KEY_CHAP_NAME,
+ (CHAR8 *) &AuthData->AuthConfig->CHAPName
+ );
//
// CHAP_R=<R>
//
- IScsiBinToHex ((UINT8 *) AuthData->CHAPResponse, ISCSI_CHAP_RSP_LEN, Response, &RspLen);
+ IScsiBinToHex (
+ (UINT8 *) AuthData->CHAPResponse,
+ ISCSI_CHAP_RSP_LEN,
+ Response,
+ &RspLen
+ );
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_RESPONSE, Response);
if (AuthData->AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL) {
@@ -454,7 +497,12 @@ IScsiCHAPToSendReq (
//
IScsiGenRandom ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN);
AuthData->OutChallengeLength = ISCSI_CHAP_RSP_LEN;
- IScsiBinToHex ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN, Challenge, &ChallengeLen);
+ IScsiBinToHex (
+ (UINT8 *) AuthData->OutChallenge,
+ ISCSI_CHAP_RSP_LEN,
+ Challenge,
+ &ChallengeLen
+ );
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_CHALLENGE, Challenge);
Conn->AuthStep = ISCSI_CHAP_STEP_FOUR;
diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.h b/NetworkPkg/IScsiDxe/IScsiCHAP.h
index 132461b84d25..59c53fcd3538 100644
--- a/NetworkPkg/IScsiDxe/IScsiCHAP.h
+++ b/NetworkPkg/IScsiDxe/IScsiCHAP.h
@@ -94,7 +94,8 @@ IScsiCHAPOnRspReceived (
@param[in, out] Pdu The PDU to send out.
@retval EFI_SUCCESS All check passed and the phase-related CHAP
- authentication info is filled into the iSCSI PDU.
+ authentication info is filled into the iSCSI
+ PDU.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
@retval EFI_PROTOCOL_ERROR Some kind of protocol error occurred.
--
2.31.1
From fa23b21d2e383b0177401fd6ba1d4533668752d7 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 26 Apr 2021 20:07:25 +0200
Subject: [PATCH 10/18] NetworkPkg/IScsiDxe: simplify
"ISCSI_CHAP_AUTH_DATA.InChallenge" size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The ISCSI_CHAP_AUTH_MAX_LEN macro is defined with value 1024.
The usage of this macro currently involves a semantic (not functional)
bug, which we're going to fix in a subsequent patch, eliminating
ISCSI_CHAP_AUTH_MAX_LEN altogether.
For now, remove the macro's usage from all
"ISCSI_CHAP_AUTH_DATA.InChallenge" contexts. This is doable without
duplicating open-coded constants.
No changes in functionality.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiCHAP.c | 2 +-
NetworkPkg/IScsiDxe/IScsiCHAP.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.c b/NetworkPkg/IScsiDxe/IScsiCHAP.c
index 5f045b07851c..8a44078268c7 100644
--- a/NetworkPkg/IScsiDxe/IScsiCHAP.c
+++ b/NetworkPkg/IScsiDxe/IScsiCHAP.c
@@ -295,7 +295,7 @@ IScsiCHAPOnRspReceived (
}
AuthData->InIdentifier = (UINT32) Result;
- AuthData->InChallengeLength = ISCSI_CHAP_AUTH_MAX_LEN;
+ AuthData->InChallengeLength = (UINT32) sizeof (AuthData->InChallenge);
IScsiHexToBin (
(UINT8 *) AuthData->InChallenge,
&AuthData->InChallengeLength,
diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.h b/NetworkPkg/IScsiDxe/IScsiCHAP.h
index 59c53fcd3538..8692c78f1d36 100644
--- a/NetworkPkg/IScsiDxe/IScsiCHAP.h
+++ b/NetworkPkg/IScsiDxe/IScsiCHAP.h
@@ -55,7 +55,7 @@ typedef struct _ISCSI_CHAP_AUTH_CONFIG_NVDATA {
typedef struct _ISCSI_CHAP_AUTH_DATA {
ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig;
UINT32 InIdentifier;
- UINT8 InChallenge[ISCSI_CHAP_AUTH_MAX_LEN];
+ UINT8 InChallenge[1024];
UINT32 InChallengeLength;
//
// Calculated CHAP Response (CHAP_R) value.
--
2.31.1
From 07594eeab62504f17438a64776825aee045a0850 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 26 Apr 2021 20:17:23 +0200
Subject: [PATCH 11/18] NetworkPkg/IScsiDxe: clean up
"ISCSI_CHAP_AUTH_DATA.OutChallengeLength"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The "ISCSI_CHAP_AUTH_DATA.OutChallenge" field is declared as a UINT8 array
with ISCSI_CHAP_AUTH_MAX_LEN (1024) elements. However, when the challenge
is generated and formatted, only ISCSI_CHAP_RSP_LEN (16) octets are used
in the array.
Change the array size to ISCSI_CHAP_RSP_LEN, and remove the (now unused)
ISCSI_CHAP_AUTH_MAX_LEN macro.
Remove the "ISCSI_CHAP_AUTH_DATA.OutChallengeLength" field, which is
superfluous too.
Most importantly, explain in a new comment *why* tying the challenge size
to the digest size (ISCSI_CHAP_RSP_LEN) has always made sense. (See also
Linux kernel commit 19f5f88ed779, "scsi: target: iscsi: tie the challenge
length to the hash digest size", 2019-11-06.) For sure, the motivation
that the new comment now explains has always been there, and has always
been the same, for IScsiDxe; it's just that now we spell it out too.
No change in peer-visible behavior.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiCHAP.c | 3 +--
NetworkPkg/IScsiDxe/IScsiCHAP.h | 9 ++++++---
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.c b/NetworkPkg/IScsiDxe/IScsiCHAP.c
index 8a44078268c7..320fd4c3b803 100644
--- a/NetworkPkg/IScsiDxe/IScsiCHAP.c
+++ b/NetworkPkg/IScsiDxe/IScsiCHAP.c
@@ -128,7 +128,7 @@ IScsiCHAPAuthTarget (
AuthData->AuthConfig->ReverseCHAPSecret,
SecretSize,
AuthData->OutChallenge,
- AuthData->OutChallengeLength,
+ ISCSI_CHAP_RSP_LEN, // ChallengeLength
VerifyRsp
);
@@ -496,7 +496,6 @@ IScsiCHAPToSendReq (
// CHAP_C=<C>
//
IScsiGenRandom ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN);
- AuthData->OutChallengeLength = ISCSI_CHAP_RSP_LEN;
IScsiBinToHex (
(UINT8 *) AuthData->OutChallenge,
ISCSI_CHAP_RSP_LEN,
diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.h b/NetworkPkg/IScsiDxe/IScsiCHAP.h
index 8692c78f1d36..06ba084c9cee 100644
--- a/NetworkPkg/IScsiDxe/IScsiCHAP.h
+++ b/NetworkPkg/IScsiDxe/IScsiCHAP.h
@@ -25,7 +25,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define ISCSI_CHAP_ALGORITHM_MD5 5
-#define ISCSI_CHAP_AUTH_MAX_LEN 1024
///
/// MD5_HASHSIZE
///
@@ -65,9 +64,13 @@ typedef struct _ISCSI_CHAP_AUTH_DATA {
//
// Auth-data to be sent out for mutual authentication.
//
+ // While the challenge size is technically independent of the hashing
+ // algorithm, it is good practice to avoid hashing *fewer bytes* than the
+ // digest size. In other words, it's good practice to feed *at least as many
+ // bytes* to the hashing algorithm as the hashing algorithm will output.
+ //
UINT32 OutIdentifier;
- UINT8 OutChallenge[ISCSI_CHAP_AUTH_MAX_LEN];
- UINT32 OutChallengeLength;
+ UINT8 OutChallenge[ISCSI_CHAP_RSP_LEN];
} ISCSI_CHAP_AUTH_DATA;
/**
--
2.31.1
From ea7b1bd5386925f8e02c0a49335a864b41763048 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 27 Apr 2021 09:49:16 +0200
Subject: [PATCH 12/18] NetworkPkg/IScsiDxe: clean up library class
dependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Sort the library class dependencies in the #include directives and in the
INF file. Remove the DpcLib class from the #include directives -- it is
not listed in the INF file, and IScsiDxe doesn't call either DpcLib API
(QueueDpc(), DispatchDpc()). No functional changes.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiDxe.inf | 6 +++---
NetworkPkg/IScsiDxe/IScsiImpl.h | 17 ++++++++---------
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiDxe.inf b/NetworkPkg/IScsiDxe/IScsiDxe.inf
index 319c7fe79a52..5ffb947abda0 100644
--- a/NetworkPkg/IScsiDxe/IScsiDxe.inf
+++ b/NetworkPkg/IScsiDxe/IScsiDxe.inf
@@ -71,6 +71,7 @@ [Packages]
NetworkPkg/NetworkPkg.dec
[LibraryClasses]
+ BaseCryptLib
BaseLib
BaseMemoryLib
DebugLib
@@ -78,14 +79,13 @@ [LibraryClasses]
HiiLib
MemoryAllocationLib
NetLib
- TcpIoLib
PrintLib
+ TcpIoLib
UefiBootServicesTableLib
UefiDriverEntryPoint
+ UefiHiiServicesLib
UefiLib
UefiRuntimeServicesTableLib
- UefiHiiServicesLib
- BaseCryptLib
[Protocols]
gEfiAcpiTableProtocolGuid ## SOMETIMES_CONSUMES ## SystemTable
diff --git a/NetworkPkg/IScsiDxe/IScsiImpl.h b/NetworkPkg/IScsiDxe/IScsiImpl.h
index 9e36da020309..2b9a080b2ec1 100644
--- a/NetworkPkg/IScsiDxe/IScsiImpl.h
+++ b/NetworkPkg/IScsiDxe/IScsiImpl.h
@@ -41,21 +41,20 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/AdapterInformation.h>
#include <Protocol/NetworkInterfaceIdentifier.h>
-#include <Library/HiiLib.h>
-#include <Library/UefiHiiServicesLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/DebugLib.h>
+#include <Library/BaseCryptLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
#include <Library/PrintLib.h>
+#include <Library/TcpIoLib.h>
#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
#include <Library/UefiLib.h>
-#include <Library/DpcLib.h>
-#include <Library/NetLib.h>
-#include <Library/TcpIoLib.h>
-#include <Library/BaseCryptLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
#include <Guid/MdeModuleHii.h>
#include <Guid/EventGroup.h>
--
2.31.1
From 4c018d9dc04a6f8ef4abe134149de5166f6692fa Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 27 Apr 2021 10:10:42 +0200
Subject: [PATCH 13/18] NetworkPkg/IScsiDxe: fix potential integer overflow in
IScsiBinToHex()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Considering IScsiBinToHex():
> if (((*HexLength) - 3) < BinLength * 2) {
> *HexLength = BinLength * 2 + 3;
> }
the following subexpressions are problematic:
(*HexLength) - 3
BinLength * 2
BinLength * 2 + 3
The first one may wrap under zero, the latter two may wrap over
MAX_UINT32.
Rewrite the calculation using SafeIntLib.
While at it, change the type of the "Index" variable from UINTN to UINT32.
The largest "Index"-based value that we calculate is
Index * 2 + 2 (with (Index == BinLength))
Because the patch makes
BinLength * 2 + 3
safe to calculate in UINT32, using UINT32 for
Index * 2 + 2 (with (Index == BinLength))
is safe too. Consistently using UINT32 improves readability.
This patch is best reviewed with "git show -W".
The integer overflows that this patch fixes are theoretical; a subsequent
patch in the series will audit the IScsiBinToHex() call sites, and show
that none of them can fail.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiDxe.inf | 1 +
NetworkPkg/IScsiDxe/IScsiImpl.h | 1 +
NetworkPkg/IScsiDxe/IScsiMisc.c | 19 +++++++++++++++----
NetworkPkg/IScsiDxe/IScsiMisc.h | 1 +
4 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiDxe.inf b/NetworkPkg/IScsiDxe/IScsiDxe.inf
index 5ffb947abda0..3c356a22b856 100644
--- a/NetworkPkg/IScsiDxe/IScsiDxe.inf
+++ b/NetworkPkg/IScsiDxe/IScsiDxe.inf
@@ -80,6 +80,7 @@ [LibraryClasses]
MemoryAllocationLib
NetLib
PrintLib
+ SafeIntLib
TcpIoLib
UefiBootServicesTableLib
UefiDriverEntryPoint
diff --git a/NetworkPkg/IScsiDxe/IScsiImpl.h b/NetworkPkg/IScsiDxe/IScsiImpl.h
index 2b9a080b2ec1..a114b31549d7 100644
--- a/NetworkPkg/IScsiDxe/IScsiImpl.h
+++ b/NetworkPkg/IScsiDxe/IScsiImpl.h
@@ -50,6 +50,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/MemoryAllocationLib.h>
#include <Library/NetLib.h>
#include <Library/PrintLib.h>
+#include <Library/SafeIntLib.h>
#include <Library/TcpIoLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiHiiServicesLib.h>
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c
index 9e4164c986bc..23f2be3e085e 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.c
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.c
@@ -322,6 +322,7 @@ IScsiMacAddrToStr (
@retval EFI_SUCCESS The binary data is converted to the hexadecimal string
and the length of the string is updated.
@retval EFI_BUFFER_TOO_SMALL The string is too small.
+ @retval EFI_BAD_BUFFER_SIZE BinLength is too large for hex encoding.
@retval EFI_INVALID_PARAMETER The IP string is malformatted.
**/
@@ -333,18 +334,28 @@ IScsiBinToHex (
IN OUT UINT32 *HexLength
)
{
- UINTN Index;
+ UINT32 HexLengthMin;
+ UINT32 HexLengthProvided;
+ UINT32 Index;
if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
return EFI_INVALID_PARAMETER;
}
- if (((*HexLength) - 3) < BinLength * 2) {
- *HexLength = BinLength * 2 + 3;
+ //
+ // Safely calculate: HexLengthMin := BinLength * 2 + 3.
+ //
+ if (RETURN_ERROR (SafeUint32Mult (BinLength, 2, &HexLengthMin)) ||
+ RETURN_ERROR (SafeUint32Add (HexLengthMin, 3, &HexLengthMin))) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ HexLengthProvided = *HexLength;
+ *HexLength = HexLengthMin;
+ if (HexLengthProvided < HexLengthMin) {
return EFI_BUFFER_TOO_SMALL;
}
- *HexLength = BinLength * 2 + 3;
//
// Prefix for Hex String.
//
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.h b/NetworkPkg/IScsiDxe/IScsiMisc.h
index 659c0268b582..71312211f7b6 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.h
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.h
@@ -156,6 +156,7 @@ IScsiAsciiStrToIp (
@retval EFI_SUCCESS The binary data is converted to the hexadecimal string
and the length of the string is updated.
@retval EFI_BUFFER_TOO_SMALL The string is too small.
+ @retval EFI_BAD_BUFFER_SIZE BinLength is too large for hex encoding.
@retval EFI_INVALID_PARAMETER The IP string is malformatted.
**/
--
2.31.1
From 6c9e2432cf976055d9b36729ffb8cf3a66721499 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 27 Apr 2021 10:26:01 +0200
Subject: [PATCH 14/18] NetworkPkg/IScsiDxe: assert that IScsiBinToHex() always
succeeds
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
IScsiBinToHex() is called for encoding:
- the answer to the target's challenge; that is, CHAP_R;
- the challenge for the target, in case mutual authentication is enabled;
that is, CHAP_C.
The initiator controls the size of both blobs, the sizes of their hex
encodings are correctly calculated in "RspLen" and "ChallengeLen".
Therefore the IScsiBinToHex() calls never fail; assert that.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiCHAP.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.c b/NetworkPkg/IScsiDxe/IScsiCHAP.c
index 320fd4c3b803..03234b616594 100644
--- a/NetworkPkg/IScsiDxe/IScsiCHAP.c
+++ b/NetworkPkg/IScsiDxe/IScsiCHAP.c
@@ -397,6 +397,7 @@ IScsiCHAPToSendReq (
UINT32 RspLen;
CHAR8 *Challenge;
UINT32 ChallengeLen;
+ EFI_STATUS BinToHexStatus;
ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION);
@@ -477,12 +478,13 @@ IScsiCHAPToSendReq (
//
// CHAP_R=<R>
//
- IScsiBinToHex (
- (UINT8 *) AuthData->CHAPResponse,
- ISCSI_CHAP_RSP_LEN,
- Response,
- &RspLen
- );
+ BinToHexStatus = IScsiBinToHex (
+ (UINT8 *) AuthData->CHAPResponse,
+ ISCSI_CHAP_RSP_LEN,
+ Response,
+ &RspLen
+ );
+ ASSERT_EFI_ERROR (BinToHexStatus);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_RESPONSE, Response);
if (AuthData->AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL) {
@@ -496,12 +498,13 @@ IScsiCHAPToSendReq (
// CHAP_C=<C>
//
IScsiGenRandom ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN);
- IScsiBinToHex (
- (UINT8 *) AuthData->OutChallenge,
- ISCSI_CHAP_RSP_LEN,
- Challenge,
- &ChallengeLen
- );
+ BinToHexStatus = IScsiBinToHex (
+ (UINT8 *) AuthData->OutChallenge,
+ ISCSI_CHAP_RSP_LEN,
+ Challenge,
+ &ChallengeLen
+ );
+ ASSERT_EFI_ERROR (BinToHexStatus);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_CHALLENGE, Challenge);
Conn->AuthStep = ISCSI_CHAP_STEP_FOUR;
--
2.31.1
From 532d9764cde299860317d3b9fc245a37eb1fa5ba Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 27 Apr 2021 10:37:26 +0200
Subject: [PATCH 15/18] NetworkPkg/IScsiDxe: reformat IScsiHexToBin() leading
comment block
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We'll need further return values for IScsiHexToBin() in a subsequent
patch; make room for them in the leading comment block of the function.
While at it, rewrap the comment block to 80 characters width.
No functional changes.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiMisc.c | 14 +++++++-------
NetworkPkg/IScsiDxe/IScsiMisc.h | 14 +++++++-------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c
index 23f2be3e085e..d73d7ef32484 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.c
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.c
@@ -376,14 +376,14 @@ IScsiBinToHex (
/**
Convert the hexadecimal string into a binary encoded buffer.
- @param[in, out] BinBuffer The binary buffer.
- @param[in, out] BinLength Length of the binary buffer.
- @param[in] HexStr The hexadecimal string.
-
- @retval EFI_SUCCESS The hexadecimal string is converted into a binary
- encoded buffer.
- @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.
+ @param[in, out] BinBuffer The binary buffer.
+ @param[in, out] BinLength Length of the binary buffer.
+ @param[in] HexStr The hexadecimal string.
+ @retval EFI_SUCCESS The hexadecimal string is converted into a
+ binary encoded buffer.
+ @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the
+ converted data.
**/
EFI_STATUS
IScsiHexToBin (
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.h b/NetworkPkg/IScsiDxe/IScsiMisc.h
index 71312211f7b6..13c165b88e42 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.h
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.h
@@ -171,14 +171,14 @@ IScsiBinToHex (
/**
Convert the hexadecimal string into a binary encoded buffer.
- @param[in, out] BinBuffer The binary buffer.
- @param[in, out] BinLength Length of the binary buffer.
- @param[in] HexStr The hexadecimal string.
-
- @retval EFI_SUCCESS The hexadecimal string is converted into a binary
- encoded buffer.
- @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.
+ @param[in, out] BinBuffer The binary buffer.
+ @param[in, out] BinLength Length of the binary buffer.
+ @param[in] HexStr The hexadecimal string.
+ @retval EFI_SUCCESS The hexadecimal string is converted into a
+ binary encoded buffer.
+ @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the
+ converted data.
**/
EFI_STATUS
IScsiHexToBin (
--
2.31.1
From f6cc8d2cc922898a2086e2e2e7211cbdcdac8a60 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 27 Apr 2021 11:02:51 +0200
Subject: [PATCH 16/18] NetworkPkg/IScsiDxe: fix IScsiHexToBin() hex parsing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The IScsiHexToBin() function has the following parser issues:
(1) If the *subject sequence* in "HexStr" is empty, the function returns
EFI_SUCCESS (with "BinLength" set to 0 on output). Such inputs should
be rejected.
(2) The function mis-handles a "HexStr" that ends with a stray nibble. For
example, if "HexStr" is "0xABC", the function decodes it to the bytes
{0xAB, 0x0C}, sets "BinLength" to 2 on output, and returns
EFI_SUCCESS. Such inputs should be rejected.
(3) If an invalid hex char is found in "HexStr", the function treats it as
end-of-hex-string, and returns EFI_SUCCESS. Such inputs should be
rejected.
All of the above cases are remotely triggerable, as shown in a subsequent
patch, which adds error checking to the IScsiHexToBin() call sites. While
the initiator is not immediately compromised, incorrectly parsing CHAP_R
from the target, in case of mutual authentication, is not great.
Extend the interface contract of IScsiHexToBin() with
EFI_INVALID_PARAMETER, for reporting issues (1) through (3), and implement
the new checks.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiMisc.c | 12 ++++++++++--
NetworkPkg/IScsiDxe/IScsiMisc.h | 1 +
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c
index d73d7ef32484..ebc2f4b7cd25 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.c
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.c
@@ -382,6 +382,7 @@ IScsiBinToHex (
@retval EFI_SUCCESS The hexadecimal string is converted into a
binary encoded buffer.
+ @retval EFI_INVALID_PARAMETER Invalid hex encoding found in HexStr.
@retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the
converted data.
**/
@@ -408,14 +409,21 @@ IScsiHexToBin (
Length = AsciiStrLen (HexStr);
+ //
+ // Reject an empty hex string; reject a stray nibble.
+ //
+ if (Length == 0 || Length % 2 != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
for (Index = 0; Index < Length; Index ++) {
TemStr[0] = HexStr[Index];
Digit = (UINT8) AsciiStrHexToUint64 (TemStr);
if (Digit == 0 && TemStr[0] != '0') {
//
- // Invalid Lun Char.
+ // Invalid Hex Char.
//
- break;
+ return EFI_INVALID_PARAMETER;
}
if ((Index & 1) == 0) {
BinBuffer [Index/2] = Digit;
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.h b/NetworkPkg/IScsiDxe/IScsiMisc.h
index 13c165b88e42..77e0f63d0ece 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.h
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.h
@@ -177,6 +177,7 @@ IScsiBinToHex (
@retval EFI_SUCCESS The hexadecimal string is converted into a
binary encoded buffer.
+ @retval EFI_INVALID_PARAMETER Invalid hex encoding found in HexStr.
@retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the
converted data.
**/
--
2.31.1
From a82cb44f4c016ae3d4ecb7620eb1cb46a205b895 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 27 Apr 2021 11:02:51 +0200
Subject: [PATCH 17/18] NetworkPkg/IScsiDxe: fix IScsiHexToBin() buffer
overflow
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The IScsiHexToBin() function documents the EFI_BUFFER_TOO_SMALL return
condition, but never actually checks whether the decoded buffer fits into
the caller-provided room (i.e., the input value of "BinLength"), and
EFI_BUFFER_TOO_SMALL is never returned. The decoding of "HexStr" can
overflow "BinBuffer".
This is remotely exploitable, as shown in a subsequent patch, which adds
error checking to the IScsiHexToBin() call sites. This issue allows the
target to compromise the initiator.
Introduce EFI_BAD_BUFFER_SIZE, in addition to the existent
EFI_BUFFER_TOO_SMALL, for reporting a special case of the buffer overflow,
plus actually catch the buffer overflow.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiMisc.c | 20 +++++++++++++++++---
NetworkPkg/IScsiDxe/IScsiMisc.h | 3 +++
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c
index ebc2f4b7cd25..ba611ad3cd61 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.c
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.c
@@ -383,6 +383,9 @@ IScsiBinToHex (
@retval EFI_SUCCESS The hexadecimal string is converted into a
binary encoded buffer.
@retval EFI_INVALID_PARAMETER Invalid hex encoding found in HexStr.
+ @retval EFI_BAD_BUFFER_SIZE The length of HexStr is too large for decoding:
+ the decoded size cannot be expressed in
+ BinLength on output.
@retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the
converted data.
**/
@@ -393,6 +396,8 @@ IScsiHexToBin (
IN CHAR8 *HexStr
)
{
+ UINTN BinLengthMin;
+ UINT32 BinLengthProvided;
UINTN Index;
UINTN Length;
UINT8 Digit;
@@ -415,6 +420,18 @@ IScsiHexToBin (
if (Length == 0 || Length % 2 != 0) {
return EFI_INVALID_PARAMETER;
}
+ //
+ // Check if the caller provides enough room for the decoded blob.
+ //
+ BinLengthMin = Length / 2;
+ if (BinLengthMin > MAX_UINT32) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ BinLengthProvided = *BinLength;
+ *BinLength = (UINT32)BinLengthMin;
+ if (BinLengthProvided < BinLengthMin) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
for (Index = 0; Index < Length; Index ++) {
TemStr[0] = HexStr[Index];
@@ -431,9 +448,6 @@ IScsiHexToBin (
BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);
}
}
-
- *BinLength = (UINT32) ((Index + 1)/2);
-
return EFI_SUCCESS;
}
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.h b/NetworkPkg/IScsiDxe/IScsiMisc.h
index 77e0f63d0ece..d09e281c90c4 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.h
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.h
@@ -178,6 +178,9 @@ IScsiBinToHex (
@retval EFI_SUCCESS The hexadecimal string is converted into a
binary encoded buffer.
@retval EFI_INVALID_PARAMETER Invalid hex encoding found in HexStr.
+ @retval EFI_BAD_BUFFER_SIZE The length of HexStr is too large for decoding:
+ the decoded size cannot be expressed in
+ BinLength on output.
@retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the
converted data.
**/
--
2.31.1
From 1b02f0d8380ce2efa13da777b02ae89b08712a38 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 27 Apr 2021 12:10:12 +0200
Subject: [PATCH 18/18] NetworkPkg/IScsiDxe: check IScsiHexToBin() return
values
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
IScsiDxe (that is, the initiator) receives two hex-encoded strings from
the iSCSI target:
- CHAP_C, where the target challenges the initiator,
- CHAP_R, where the target answers the challenge from the initiator (in
case the initiator wants mutual authentication).
Accordingly, we have two IScsiHexToBin() call sites:
- At the CHAP_C decoding site, check whether the decoding succeeds. The
decoded buffer ("AuthData->InChallenge") can accommodate 1024 bytes,
which is a permissible restriction on the target, per
<https://tools.ietf.org/html/rfc7143#section-12.1.3>. Shorter challenges
from the target are acceptable.
- At the CHAP_R decoding site, enforce that the decoding both succeed, and
provide exactly ISCSI_CHAP_RSP_LEN bytes. CHAP_R contains the digest
calculated by the target, therefore it must be of fixed size. We may
only call IScsiCHAPAuthTarget() if "TargetRsp" has been fully populated.
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3356
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
---
NetworkPkg/IScsiDxe/IScsiCHAP.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.c b/NetworkPkg/IScsiDxe/IScsiCHAP.c
index 03234b616594..f89d256bc110 100644
--- a/NetworkPkg/IScsiDxe/IScsiCHAP.c
+++ b/NetworkPkg/IScsiDxe/IScsiCHAP.c
@@ -296,11 +296,15 @@ IScsiCHAPOnRspReceived (
AuthData->InIdentifier = (UINT32) Result;
AuthData->InChallengeLength = (UINT32) sizeof (AuthData->InChallenge);
- IScsiHexToBin (
- (UINT8 *) AuthData->InChallenge,
- &AuthData->InChallengeLength,
- Challenge
- );
+ Status = IScsiHexToBin (
+ (UINT8 *) AuthData->InChallenge,
+ &AuthData->InChallengeLength,
+ Challenge
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_PROTOCOL_ERROR;
+ goto ON_EXIT;
+ }
Status = IScsiCHAPCalculateResponse (
AuthData->InIdentifier,
AuthData->AuthConfig->CHAPSecret,
@@ -343,7 +347,11 @@ IScsiCHAPOnRspReceived (
}
RspLen = ISCSI_CHAP_RSP_LEN;
- IScsiHexToBin (TargetRsp, &RspLen, Response);
+ Status = IScsiHexToBin (TargetRsp, &RspLen, Response);
+ if (EFI_ERROR (Status) || RspLen != ISCSI_CHAP_RSP_LEN) {
+ Status = EFI_PROTOCOL_ERROR;
+ goto ON_EXIT;
+ }
//
// Check the CHAP Name and Response replied by Target.
--
2.31.1