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()