28.3 Casting Pointers

The example below shows an example that generates an alignment fault on an IPF platform. The first read access through SmallValuePointer is aligned because LargeValue is on a 64-bit boundary. However, the second read access though SmallValuePointer generates an alignment fault because SmallValuePointer is not on a 32-bit boundary. The problem is that an 8-bit pointer was cast to a 32-bit pointer. Whenever a cast is made from a pointer to a smaller data type to a pointer to a larger data type, there is a chance that the pointer to the larger data type is unaligned.

Example 243-Pointer-cast alignment fault
#include <Uefi.h>

UINT64 LargeValue;
UINT32 *SmallValuePointer;
UINT32 SmallValue;

SmallValuePointer = (UINT32 *) &LargeValue;

//
// Works
//
SmallValue        = *SmallValuePointer;
SmallValuePointer = (UINT32 *)((UINT8 *)&LargeValue + 1);
//
// Fails. Generates an alignment fault
//
SmallValue        = *SmallValuePointer;

Example 244, below, shows the same example as Example 243, above, but has been modified to prevent the alignment fault. The second read access through SmallValuePointer is replaced with a call to the EDK II library BaseLib function called ReadUnaligned32() that treats the 32-bit value as an array of bytes. The individual bytes are read and combined into a 32-bit value. The generated object code is larger and slower, but it is functional on all CPU architectures supported by the UEFI Specification.

Example 244-Corrected pointer-cast alignment fault
#include <Uefi.h>
#include <Library/BaseLib.h>

UINT64 LargeValue;
UINT32 *SmallValuePointer;
UINT32 SmallValue;

SmallValuePointer = (UINT32 *) &LargeValue;

//
// Works
//
SmallValue        = *SmallValuePointer;

SmallValuePointer = (UINT32 *)((UINT8 *)&LargeValue + 1);

//
// Works
//
SmallValue        = ReadUnaligned32 (SmallValuePointer);

EDK II library BaseLib provides several functions to help perform unaligned accessed in a safe manner. These functions perform a direct access on CPU architectures that do not generate alignment faults, and break the access up into small aligned pieces on CPU architectures that do generate alignment faults. The list of unaligned access functions from the EDK II library BaseLib includes the following:

  • ReadUnaligned64()

  • ReadUnaligned32()

  • ReadUnaligned24()

  • ReadUnaligned16()

  • WriteUnaligned64()

  • WriteUnaligned32()

  • WriteUnaligned24()

  • WriteUnaligned16()