I was going through the following code and came across the following snippet.
EFI_STATUS
EFIAPI
PeiCreateHob (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN UINT16 Type,
IN UINT16 Length,
IN OUT VOID **Hob
)
{
EFI_STATUS Status;
EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
EFI_HOB_GENERIC_HEADER *HobEnd;
EFI_PHYSICAL_ADDRESS FreeMemory;
Status = PeiGetHobList (PeiServices, Hob);
if (EFI_ERROR(Status)) {
return Status;
}
HandOffHob = *Hob;
//
// Check Length to avoid data overflow.
//
if (0x10000 - Length <= 0x7) {
return EFI_INVALID_PARAMETER;
}
Length = (UINT16)((Length + 0x7) & (~0x7));
...
I don't get what we are achieving with the following operation:
Length = (UINT16)((Length + 0x7) & (~0x7));
I know that the length would be 16 bit aligned. But why are we ANDing with all zeros? We would be losing the LSB 3 bits in the operation as I understand. What's the use of this operation?
The operation performs two significant steps:
Length
Length
value.Part 1: Rounding Up
If the lower three bits of
Length
are in anyway lit (anything besides000
), an increment by0x7
(111
in binary) will propagate via carry to the bits above the lower three. For000
in the lower three bits, the lower three bits simply become111
and there is no carry. For example:Another example:
And finally, an example that is already clear on the lower three bits (and therefore a multiple of 8):
Part 2: Culling Lower Bits
Once the value is rounded up, the lower three bits are culled to ensure the final result is a multiple of 8. Using the examples we had before
Next example
And our final example:
In summary, this simply sets
Length
to be the closest value equal-to or above the current value that is a multiple of8
. That's it.