28.4 Packed Structures

The following example shows another example that generates an alignment fault on an IPF platform. The first read access from MyStructure.First always works because the 8-bit value is always aligned. However, the second read access from MyStructure.Second always fails because the 32-bit value is never aligned on a 4-byte boundary.

Example 245-Packed structure alignment fault
#include <Uefi.h>

#pragma pack(1)
typedef struct {
  UINT8  First;
  UINT32 Second;
} MY_STRUCTURE;
#pragma pack()

MY_STRUCTURE MyStructure;
UINT8        FirstValue;
UINT32       SecondValue;

//
// Works
//
FirstValue   = MyStructure.First;

//
// Fails. Generates an alignment fault
//
SecondValue  = MyStructure.Second;

The next example shows the same example as Example 245, above, but has been modified to prevent the alignment fault. The second read access from MyStructure.Second 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 246-Corrected packed structure alignment fault
#include <Uefi.h>
#include <Library/BaseLib.h>

#pragma pack(1)
typedef struct {
  UINT8 First;
  UINT32 Second;
} MY_STRUCTURE;
#pragma pack()

MY_STRUCTURE  MyStructure;
UINT8         FirstValue;
UINT32        SecondValue;

//
// Works
//
FirstValue  = MyStructure.First;

//
// Works
//
SecondValue = ReadUnaligned32 ((VOID *)&MyStructure.Second);

If a data structure is copied from one location to another, then both the source and the destination pointers for the copy operation should be aligned on a 64-bit boundary. The EDK II library BaseMemoryLib provides the CopyMem() service that handles unaligned copy operations, so an alignment fault is never generated by the copy operation itself.

However, if the fields of the data structure at the destination location are accessed, they may generate alignment faults if the destination address is not aligned on a 64-bit boundary. There are cases where an aligned structure may be copied to an unaligned destination, but the fields of the destination buffer must not be accessed after the copy operation is completed. An example of this case is when a packed data structure is built and stored on a mass storage device or transmitted on a network.