Reputation: 1350
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?
Upvotes: 0
Views: 174
Reputation: 66194
Length = (UINT16)((Length + 0x7) & (~0x7));
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 besides 000
), an increment by 0x7
(111
in binary) will propagate via carry to the bits above the lower three. For 000
in the lower three bits, the lower three bits simply become 111
and there is no carry. For example:
5 - 00000101
7 - 00000111
=============
12 - 00001100
^-------note carry
Another example:
250 - 11111010
7 - 00000111
===============
257 - 100000001
And finally, an example that is already clear on the lower three bits (and therefore a multiple of 8):
24 - 00011000
7 - 00000111
=============
31 - 00011111
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
5 - 00000101
+ 7 - 00000111
===============
12 - 00001100
& ~7 - 11111000
===============
8 00001000
Next example
250 - 11111010
+ 7 - 00000111
================
257 - 100000001
& ~7 - 111111000
================
256 - 100000000
And our final example:
24 - 00011000
+ 7 - 00000111
===============
31 - 00011111
& ~7 - 11111000
===============
24 - 00011000
In summary, this simply sets Length
to be the closest value equal-to or above the current value that is a multiple of 8
. That's it.
Upvotes: 3