mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-30 02:33:44 +01:00 
			
		
		
		
	REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2048 Use new STATIC_ASSERT macro instead of VERIFY_SIZE_OF. Signed-off-by: Vitaly Cheptsov <vit9696@protonmail.com> Reviewed-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Zhichao Gao <zhichao.gao@intel.com> Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
		
			
				
	
	
		
			253 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   This contains the business logic for the module-specific Reset Helper functions.
 | |
| 
 | |
|   Copyright (c) 2017 - 2019 Intel Corporation. All rights reserved.<BR>
 | |
|   Copyright (c) 2016 Microsoft Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| #include <Uefi.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/ResetSystemLib.h>
 | |
| 
 | |
| #pragma pack(1)
 | |
| typedef struct {
 | |
|   CHAR16 NullTerminator;
 | |
|   GUID   ResetSubtype;
 | |
| } RESET_UTILITY_GUID_SPECIFIC_RESET_DATA;
 | |
| #pragma pack()
 | |
| 
 | |
| STATIC_ASSERT (
 | |
|   sizeof (RESET_UTILITY_GUID_SPECIFIC_RESET_DATA) == 18,
 | |
|   "sizeof (RESET_UTILITY_GUID_SPECIFIC_RESET_DATA) is expected to be 18 bytes"
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This is a shorthand helper function to reset with reset type and a subtype
 | |
|   so that the caller doesn't have to bother with a function that has half
 | |
|   a dozen parameters.
 | |
| 
 | |
|   This will generate a reset with status EFI_SUCCESS, a NULL string, and
 | |
|   no custom data. The subtype will be formatted in such a way that it can be
 | |
|   picked up by notification registrations and custom handlers.
 | |
| 
 | |
|   NOTE: This call will fail if the architectural ResetSystem underpinnings
 | |
|         are not initialized. For DXE, you can add gEfiResetArchProtocolGuid
 | |
|         to your DEPEX.
 | |
| 
 | |
|   @param[in]  ResetType     The default EFI_RESET_TYPE of the reset.
 | |
|   @param[in]  ResetSubtype  GUID pointer for the reset subtype to be used.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| ResetSystemWithSubtype (
 | |
|   IN EFI_RESET_TYPE     ResetType,
 | |
|   IN CONST  GUID        *ResetSubtype
 | |
|   )
 | |
| {
 | |
|   RESET_UTILITY_GUID_SPECIFIC_RESET_DATA  ResetData;
 | |
| 
 | |
|   ResetData.NullTerminator = CHAR_NULL;
 | |
|   CopyGuid (
 | |
|     (GUID *)((UINT8 *)&ResetData + OFFSET_OF (RESET_UTILITY_GUID_SPECIFIC_RESET_DATA, ResetSubtype)),
 | |
|     ResetSubtype
 | |
|     );
 | |
| 
 | |
|   ResetSystem (ResetType, EFI_SUCCESS, sizeof (ResetData), &ResetData);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This is a shorthand helper function to reset with the reset type
 | |
|   'EfiResetPlatformSpecific' and a subtype so that the caller doesn't
 | |
|   have to bother with a function that has half a dozen parameters.
 | |
| 
 | |
|   This will generate a reset with status EFI_SUCCESS, a NULL string, and
 | |
|   no custom data. The subtype will be formatted in such a way that it can be
 | |
|   picked up by notification registrations and custom handlers.
 | |
| 
 | |
|   NOTE: This call will fail if the architectural ResetSystem underpinnings
 | |
|         are not initialized. For DXE, you can add gEfiResetArchProtocolGuid
 | |
|         to your DEPEX.
 | |
| 
 | |
|   @param[in]  ResetSubtype  GUID pointer for the reset subtype to be used.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| ResetPlatformSpecificGuid (
 | |
|   IN CONST  GUID        *ResetSubtype
 | |
|   )
 | |
| {
 | |
|   ResetSystemWithSubtype (EfiResetPlatformSpecific, ResetSubtype);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function examines the DataSize and ResetData parameters passed to
 | |
|   to ResetSystem() and detemrines if the ResetData contains a Null-terminated
 | |
|   Unicode string followed by a GUID specific subtype.  If the GUID specific
 | |
|   subtype is present, then a pointer to the GUID value in ResetData is returned.
 | |
| 
 | |
|   @param[in]  DataSize    The size, in bytes, of ResetData.
 | |
|   @param[in]  ResetData   Pointer to the data buffer passed into ResetSystem().
 | |
| 
 | |
|   @retval     Pointer     Pointer to the GUID value in ResetData.
 | |
|   @retval     NULL        ResetData is NULL.
 | |
|   @retval     NULL        ResetData does not start with a Null-terminated
 | |
|                           Unicode string.
 | |
|   @retval     NULL        A Null-terminated Unicode string is present, but there
 | |
|                           are less than sizeof (GUID) bytes after the string.
 | |
|   @retval     NULL        No subtype is found.
 | |
| 
 | |
| **/
 | |
| GUID *
 | |
| EFIAPI
 | |
| GetResetPlatformSpecificGuid (
 | |
|   IN UINTN       DataSize,
 | |
|   IN CONST VOID  *ResetData
 | |
|   )
 | |
| {
 | |
|   UINTN          ResetDataStringSize;
 | |
|   GUID           *ResetSubtypeGuid;
 | |
| 
 | |
|   //
 | |
|   // Make sure parameters are valid
 | |
|   //
 | |
|   if ((ResetData == NULL) || (DataSize < sizeof (GUID))) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Determine the number of bytes in the Null-terminated Unicode string
 | |
|   // at the beginning of ResetData including the Null terminator.
 | |
|   //
 | |
|   ResetDataStringSize = StrnSizeS (ResetData, (DataSize / sizeof (CHAR16)));
 | |
| 
 | |
|   //
 | |
|   // Now, assuming that we have enough data for a GUID after the string, the
 | |
|   // GUID should be immediately after the string itself.
 | |
|   //
 | |
|   if ((ResetDataStringSize < DataSize) && (DataSize - ResetDataStringSize) >= sizeof (GUID)) {
 | |
|     ResetSubtypeGuid = (GUID *)((UINT8 *)ResetData + ResetDataStringSize);
 | |
|     DEBUG ((DEBUG_VERBOSE, "%a - Detected reset subtype %g...\n", __FUNCTION__, ResetSubtypeGuid));
 | |
|     return ResetSubtypeGuid;
 | |
|   }
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This is a helper function that creates the reset data buffer that can be
 | |
|   passed into ResetSystem().
 | |
| 
 | |
|   The reset data buffer is returned in ResetData and contains ResetString
 | |
|   followed by the ResetSubtype GUID followed by the ExtraData.
 | |
| 
 | |
|   NOTE: Strings are internally limited by MAX_UINT16.
 | |
| 
 | |
|   @param[in, out] ResetDataSize  On input, the size of the ResetData buffer. On
 | |
|                                  output, either the total number of bytes
 | |
|                                  copied, or the required buffer size.
 | |
|   @param[in, out] ResetData      A pointer to the buffer in which to place the
 | |
|                                  final structure.
 | |
|   @param[in]      ResetSubtype   Pointer to the GUID specific subtype.  This
 | |
|                                  parameter is optional and may be NULL.
 | |
|   @param[in]      ResetString    Pointer to a Null-terminated Unicode string
 | |
|                                  that describes the reset.  This parameter is
 | |
|                                  optional and may be NULL.
 | |
|   @param[in]      ExtraDataSize  The size, in bytes, of ExtraData buffer.
 | |
|   @param[in]      ExtraData      Pointer to a buffer of extra data.  This
 | |
|                                  parameter is optional and may be NULL.
 | |
| 
 | |
|   @retval     RETURN_SUCCESS             ResetDataSize and ResetData are updated.
 | |
|   @retval     RETURN_INVALID_PARAMETER   ResetDataSize is NULL.
 | |
|   @retval     RETURN_INVALID_PARAMETER   ResetData is NULL.
 | |
|   @retval     RETURN_INVALID_PARAMETER   ExtraData was provided without a
 | |
|                                          ResetSubtype. This is not supported by the
 | |
|                                          UEFI spec.
 | |
|   @retval     RETURN_BUFFER_TOO_SMALL    An insufficient buffer was provided.
 | |
|                                          ResetDataSize is updated with minimum size
 | |
|                                          required.
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| BuildResetData (
 | |
|   IN OUT   UINTN     *ResetDataSize,
 | |
|   IN OUT   VOID      *ResetData,
 | |
|   IN CONST GUID      *ResetSubtype  OPTIONAL,
 | |
|   IN CONST CHAR16    *ResetString   OPTIONAL,
 | |
|   IN       UINTN     ExtraDataSize  OPTIONAL,
 | |
|   IN CONST VOID      *ExtraData     OPTIONAL
 | |
|   )
 | |
| {
 | |
|   UINTN  ResetStringSize;
 | |
|   UINTN  ResetDataBufferSize;
 | |
|   UINT8  *Data;
 | |
| 
 | |
|   //
 | |
|   // If the size return pointer is NULL.
 | |
|   //
 | |
|   if (ResetDataSize == NULL) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
|   //
 | |
|   // If extra data is indicated, but pointer is NULL.
 | |
|   //
 | |
|   if (ExtraDataSize > 0 && ExtraData == NULL) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
|   //
 | |
|   // If extra data is indicated, but no subtype GUID is supplied.
 | |
|   //
 | |
|   if (ResetSubtype == NULL && ExtraDataSize > 0) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Determine the final string.
 | |
|   //
 | |
|   if (ResetString == NULL) {
 | |
|     ResetString = L"";     // Use an empty string.
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Calculate the total buffer required for ResetData.
 | |
|   //
 | |
|   ResetStringSize     = StrnSizeS (ResetString, MAX_UINT16);
 | |
|   ResetDataBufferSize = ResetStringSize + ExtraDataSize;
 | |
|   if (ResetSubtype != NULL) {
 | |
|     ResetDataBufferSize += sizeof (GUID);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // At this point, if the buffer isn't large enough (or if
 | |
|   // the buffer is NULL) we cannot proceed.
 | |
|   //
 | |
|   if (*ResetDataSize < ResetDataBufferSize) {
 | |
|     *ResetDataSize = ResetDataBufferSize;
 | |
|     return RETURN_BUFFER_TOO_SMALL;
 | |
|   }
 | |
|   *ResetDataSize = ResetDataBufferSize;
 | |
|   if (ResetData == NULL) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fill in ResetData with ResetString, the ResetSubtype GUID, and extra data
 | |
|   //
 | |
|   Data = (UINT8 *)ResetData;
 | |
|   CopyMem (Data, ResetString, ResetStringSize);
 | |
|   Data += ResetStringSize;
 | |
|   if (ResetSubtype != NULL) {
 | |
|     CopyMem (Data, ResetSubtype, sizeof (GUID));
 | |
|     Data += sizeof (GUID);
 | |
|   }
 | |
|   if (ExtraDataSize > 0) {
 | |
|     CopyMem (Data, ExtraData, ExtraDataSize);
 | |
|   }
 | |
| 
 | |
|   return RETURN_SUCCESS;
 | |
| }
 |