Introduce 'Start' and 'End' variables to make it easier to follow the
logic and code flow. Also add a ascii art diagram (based on a
suggestion by Laszlo).
This also fixes the 'Size' calculation for the NorFlashRead() call.
Without this patch the code will read only one instead of two
P30_MAX_BUFFER_SIZE_IN_BYTES blocks in case '*NumBytes' is smaller than
P30_MAX_BUFFER_SIZE_IN_BYTES but 'Offset + *NumBytes' is not, i.e. the
update range crosses a P30_MAX_BUFFER_SIZE_IN_BYTES boundary.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 35 ++++++++++++++++++++------
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
index 7f4743b00399..54251633d0ee 100644
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
@@ -520,6 +520,7 @@ NorFlashWriteSingleBlock (
UINTN BlockSize;
UINTN BlockAddress;
UINT8 *OrigData;
+ UINTN Start, End;
DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
@@ -555,7 +556,27 @@ NorFlashWriteSingleBlock (
// To avoid pathological cases were a 2 byte write is disregarded because it
// occurs right at a 128 byte buffered write alignment boundary, permit up to
// twice the max buffer size, and perform two writes if needed.
- if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
+ //
+ // 0 128 256
+ // [----------------|----------------]
+ // ^ ^ ^ ^
+ // | | | |
+ // | | | End, the next "word" boundary beyond
+ // | | | the (logical) update
+ // | | |
+ // | | (Offset & 0x7F) + NumBytes; i.e., the Offset inside
+ // | | (or just past) the *double-word* such that Offset is
+ // | | the *exclusive* end of the (logical) update.
+ // | |
+ // | Offset & BOUNDARY_OF_32_WORDS; i.e., Offset within the "word";
+ // | this is where the (logical) update is supposed to start
+ // |
+ // Start = Offset & ~BOUNDARY_OF_32_WORDS; i.e., Offset truncated to "word" boundary
+
+ Start = Offset & ~BOUNDARY_OF_32_WORDS;
+ End = ALIGN_VALUE (Offset + *NumBytes, P30_MAX_BUFFER_SIZE_IN_BYTES);
+
+ if ((End - Start) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
// Check to see if we need to erase before programming the data into NOR.
// If the destination bits are only changing from 1s to 0s we can just write.
// After a block is erased all bits in the block is set to 1.
@@ -565,8 +586,8 @@ NorFlashWriteSingleBlock (
Status = NorFlashRead (
Instance,
Lba,
- Offset & ~BOUNDARY_OF_32_WORDS,
- (*NumBytes | BOUNDARY_OF_32_WORDS) + 1,
+ Start,
+ End - Start,
Instance->ShadowBuffer
);
if (EFI_ERROR (Status)) {
@@ -601,7 +622,7 @@ NorFlashWriteSingleBlock (
Status = NorFlashWriteBuffer (
Instance,
- BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS),
+ BlockAddress + Start,
P30_MAX_BUFFER_SIZE_IN_BYTES,
Instance->ShadowBuffer
);
@@ -609,12 +630,10 @@ NorFlashWriteSingleBlock (
goto Exit;
}
- if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) > P30_MAX_BUFFER_SIZE_IN_BYTES) {
- BlockAddress += P30_MAX_BUFFER_SIZE_IN_BYTES;
-
+ if ((End - Start) > P30_MAX_BUFFER_SIZE_IN_BYTES) {
Status = NorFlashWriteBuffer (
Instance,
- BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS),
+ BlockAddress + Start + P30_MAX_BUFFER_SIZE_IN_BYTES,
P30_MAX_BUFFER_SIZE_IN_BYTES,
Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES
);
--
2.43.0
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#113833): https://edk2.groups.io/g/devel/message/113833
Mute This Topic: https://groups.io/mt/103741669/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
On 1/15/24 16:59, Gerd Hoffmann wrote:
> Introduce 'Start' and 'End' variables to make it easier to follow the
> logic and code flow. Also add a ascii art diagram (based on a
> suggestion by Laszlo).
>
> This also fixes the 'Size' calculation for the NorFlashRead() call.
> Without this patch the code will read only one instead of two
> P30_MAX_BUFFER_SIZE_IN_BYTES blocks in case '*NumBytes' is smaller than
> P30_MAX_BUFFER_SIZE_IN_BYTES but 'Offset + *NumBytes' is not, i.e. the
> update range crosses a P30_MAX_BUFFER_SIZE_IN_BYTES boundary.
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
> OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 35 ++++++++++++++++++++------
> 1 file changed, 27 insertions(+), 8 deletions(-)
>
> diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
> index 7f4743b00399..54251633d0ee 100644
> --- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
> +++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
> @@ -520,6 +520,7 @@ NorFlashWriteSingleBlock (
> UINTN BlockSize;
> UINTN BlockAddress;
> UINT8 *OrigData;
> + UINTN Start, End;
>
> DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
>
> @@ -555,7 +556,27 @@ NorFlashWriteSingleBlock (
> // To avoid pathological cases were a 2 byte write is disregarded because it
> // occurs right at a 128 byte buffered write alignment boundary, permit up to
> // twice the max buffer size, and perform two writes if needed.
> - if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
> + //
> + // 0 128 256
> + // [----------------|----------------]
> + // ^ ^ ^ ^
> + // | | | |
> + // | | | End, the next "word" boundary beyond
> + // | | | the (logical) update
> + // | | |
> + // | | (Offset & 0x7F) + NumBytes; i.e., the Offset inside
> + // | | (or just past) the *double-word* such that Offset is
> + // | | the *exclusive* end of the (logical) update.
Obviously, when I proposed this diagram, I messed up this text.
Clearly, there's no better time for making a mistake in a comment than
when complaining about comments... :)
Two warts:
- 0x7F has not been replaced with BOUNDARY_OF_32_WORDS
- the uppercase "Offset" identifier (= proper noun), from my original
proposal, is misleading here. The common noun "offset" is what's need.
So I suggest refreshing it as:
// | | (Offset & BOUNDARY_OF_32_WORDS) + NumBytes;
// | | i.e., the relative offset inside (or just past)
// | | the *double-word* such that it is the
// | | *exclusive* end of the (logical) update.
With that comment update:
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Thanks!
Laszlo
> + // | |
> + // | Offset & BOUNDARY_OF_32_WORDS; i.e., Offset within the "word";
> + // | this is where the (logical) update is supposed to start
> + // |
> + // Start = Offset & ~BOUNDARY_OF_32_WORDS; i.e., Offset truncated to "word" boundary
> +
> + Start = Offset & ~BOUNDARY_OF_32_WORDS;
> + End = ALIGN_VALUE (Offset + *NumBytes, P30_MAX_BUFFER_SIZE_IN_BYTES);
> +
> + if ((End - Start) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
> // Check to see if we need to erase before programming the data into NOR.
> // If the destination bits are only changing from 1s to 0s we can just write.
> // After a block is erased all bits in the block is set to 1.
> @@ -565,8 +586,8 @@ NorFlashWriteSingleBlock (
> Status = NorFlashRead (
> Instance,
> Lba,
> - Offset & ~BOUNDARY_OF_32_WORDS,
> - (*NumBytes | BOUNDARY_OF_32_WORDS) + 1,
> + Start,
> + End - Start,
> Instance->ShadowBuffer
> );
> if (EFI_ERROR (Status)) {
> @@ -601,7 +622,7 @@ NorFlashWriteSingleBlock (
>
> Status = NorFlashWriteBuffer (
> Instance,
> - BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS),
> + BlockAddress + Start,
> P30_MAX_BUFFER_SIZE_IN_BYTES,
> Instance->ShadowBuffer
> );
> @@ -609,12 +630,10 @@ NorFlashWriteSingleBlock (
> goto Exit;
> }
>
> - if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) > P30_MAX_BUFFER_SIZE_IN_BYTES) {
> - BlockAddress += P30_MAX_BUFFER_SIZE_IN_BYTES;
> -
> + if ((End - Start) > P30_MAX_BUFFER_SIZE_IN_BYTES) {
> Status = NorFlashWriteBuffer (
> Instance,
> - BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS),
> + BlockAddress + Start + P30_MAX_BUFFER_SIZE_IN_BYTES,
> P30_MAX_BUFFER_SIZE_IN_BYTES,
> Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES
> );
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#113893): https://edk2.groups.io/g/devel/message/113893
Mute This Topic: https://groups.io/mt/103741669/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/3901457/1787277/102458076/xyzzy [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2026 Red Hat, Inc.