From 7b278993d0b23b3bd31210fc0bb054bf337d5a8d Mon Sep 17 00:00:00 2001 From: Miroslav Rezanina Date: Wed, 31 Jan 2024 04:45:05 -0500 Subject: [PATCH] * Wed Jan 31 2024 Miroslav Rezanina - 20231122-4 - edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch [RHEL-20963] - edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch [RHEL-20963] - edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch [RHEL-20963] - edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch [RHEL-20963] - edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch [RHEL-20963] - edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch [RHEL-20963] - Resolves: RHEL-20963 ([rhel9] guest fails to boot due to ASSERT error) --- ...lashDxe-ValidateFvHeader-unwritten-s.patch | 48 +++++++ ...lashDxe-add-a-loop-for-NorFlashWrite.patch | 74 ++++++++++ ...lashDxe-add-casts-to-UINTN-and-UINT3.patch | 56 ++++++++ ...lashDxe-allow-larger-writes-without-.patch | 66 +++++++++ ...lashDxe-clarify-block-write-logic-fi.patch | 111 +++++++++++++++ ...lashDxe-move-DoErase-code-block-into.patch | 132 ++++++++++++++++++ edk2.spec | 24 +++- 7 files changed, 510 insertions(+), 1 deletion(-) create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch b/edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch new file mode 100644 index 0000000..d63468d --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch @@ -0,0 +1,48 @@ +From cfcef96bb3c63342d4fb87cf0cda8e9dcaef9b2b Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:04 +0100 +Subject: [PATCH 5/6] OvmfPkg/VirtNorFlashDxe: ValidateFvHeader: unwritten + state is EOL too + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 52: OvmfPkg/VirtNorFlashDxe: backport more fixes. +RH-Jira: RHEL-20963 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina +RH-Commit: [5/6] 24a9f2d03eeaf61ea8f0ea5a40f0921994b08688 (kraxel.rh/centos-src-edk2) + +It is possible to find variable entries with State being 0xff, i.e. not +updated since flash block erase. This indicates the variable driver +could not complete the header write while appending a new entry, and +therefore State was not set to VAR_HEADER_VALID_ONLY. + +This can only happen at the end of the variable list, so treat this as +additional "end of variable list" condition. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-6-kraxel@redhat.com> +(cherry picked from commit 735d0a5e2e25c1577bf9bea7826da937ca38169d) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +index 8fcd999ac6..c8b5e0be13 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +@@ -302,6 +302,11 @@ ValidateFvHeader ( + break; + } + ++ if (VarHeader->State == 0xff) { ++ DEBUG ((DEBUG_INFO, "%a: end of var list (unwritten state)\n", __func__)); ++ break; ++ } ++ + VarName = NULL; + switch (VarHeader->State) { + // usage: State = VAR_HEADER_VALID_ONLY +-- +2.39.3 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch b/edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch new file mode 100644 index 0000000..47a1a95 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch @@ -0,0 +1,74 @@ +From a82176278e664c3955197d1e076188471d88a422 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:02 +0100 +Subject: [PATCH 3/6] OvmfPkg/VirtNorFlashDxe: add a loop for + NorFlashWriteBuffer calls. + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 52: OvmfPkg/VirtNorFlashDxe: backport more fixes. +RH-Jira: RHEL-20963 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina +RH-Commit: [3/6] 993426855451252f1126348e107e386b07314bfd (kraxel.rh/centos-src-edk2) + +Replace the two NorFlashWriteBuffer() calls with a loop containing a +single NorFlashWriteBuffer() call. + +With the changes in place the code is able to handle updates larger +than two P30_MAX_BUFFER_SIZE_IN_BYTES blocks, even though the patch +does not actually change the size limit. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-4-kraxel@redhat.com> +(cherry picked from commit 28ffd726894f11a587a6ac7f71a4c4af341e24d2) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 88a4d2c23f..3d1343b381 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -521,6 +521,7 @@ NorFlashWriteSingleBlock ( + UINTN BlockAddress; + UINT8 *OrigData; + UINTN Start, End; ++ UINT32 Index, Count; + + DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer)); + +@@ -621,23 +622,17 @@ NorFlashWriteSingleBlock ( + goto Exit; + } + +- Status = NorFlashWriteBuffer ( +- Instance, +- BlockAddress + Start, +- P30_MAX_BUFFER_SIZE_IN_BYTES, +- Instance->ShadowBuffer +- ); +- if (EFI_ERROR (Status)) { +- goto Exit; +- } +- +- if ((End - Start) > P30_MAX_BUFFER_SIZE_IN_BYTES) { ++ Count = (End - Start) / P30_MAX_BUFFER_SIZE_IN_BYTES; ++ for (Index = 0; Index < Count; Index++) { + Status = NorFlashWriteBuffer ( + Instance, +- BlockAddress + Start + P30_MAX_BUFFER_SIZE_IN_BYTES, ++ BlockAddress + Start + Index * P30_MAX_BUFFER_SIZE_IN_BYTES, + P30_MAX_BUFFER_SIZE_IN_BYTES, +- Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES ++ Instance->ShadowBuffer + Index * P30_MAX_BUFFER_SIZE_IN_BYTES + ); ++ if (EFI_ERROR (Status)) { ++ goto Exit; ++ } + } + + Exit: +-- +2.39.3 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch b/edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch new file mode 100644 index 0000000..5ac4d29 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch @@ -0,0 +1,56 @@ +From 74d2d4b58efe72b931bd2979254cb0fa02a38276 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:00 +0100 +Subject: [PATCH 1/6] OvmfPkg/VirtNorFlashDxe: add casts to UINTN and UINT32 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 52: OvmfPkg/VirtNorFlashDxe: backport more fixes. +RH-Jira: RHEL-20963 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina +RH-Commit: [1/6] ad54e96a5f20907ac591fcfcc0961d353953c4f1 (kraxel.rh/centos-src-edk2) + +This is needed to avoid bit operations being applied to signed integers. + +Suggested-by: László Érsek +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-2-kraxel@redhat.com> +(cherry picked from commit 0395045ae307c43a41f72ca9a8bf4eb8f16b2fe0) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 2 +- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 1afd60ce66..7f4743b003 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -581,7 +581,7 @@ NorFlashWriteSingleBlock ( + // contents, while checking whether the old version had any bits cleared + // that we want to set. In that case, we will need to erase the block first. + for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) { +- if (~OrigData[CurOffset] & Buffer[CurOffset]) { ++ if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) { + goto DoErase; + } + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +index b7f5d208b2..455eafacc2 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +@@ -61,7 +61,7 @@ + #define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128) + #define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4)) + #define MAX_BUFFERED_PROG_ITERATIONS 10000000 +-#define BOUNDARY_OF_32_WORDS 0x7F ++#define BOUNDARY_OF_32_WORDS ((UINTN)0x7F) + + // CFI Addresses + #define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10 +-- +2.39.3 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch b/edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch new file mode 100644 index 0000000..ed1f4a1 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch @@ -0,0 +1,66 @@ +From 75774a03a6e0d2f5ca8103bab8d7d31e40624edd Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:03 +0100 +Subject: [PATCH 4/6] OvmfPkg/VirtNorFlashDxe: allow larger writes without + block erase + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 52: OvmfPkg/VirtNorFlashDxe: backport more fixes. +RH-Jira: RHEL-20963 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina +RH-Commit: [4/6] 4bc6828b395ef708201a49001348bb61a0108339 (kraxel.rh/centos-src-edk2) + +Raise the limit for writes without block erase from two to four +P30_MAX_BUFFER_SIZE_IN_BYTES blocks. With this in place almost all efi +variable updates are handled without block erase. With the old limit +some variable updates (with device paths) took the block erase code +path. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-5-kraxel@redhat.com> +(cherry picked from commit b25733c97442513890ae6bb8e10fd340f13844a7) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 3d1343b381..3d1d20daa1 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -550,13 +550,15 @@ NorFlashWriteSingleBlock ( + return EFI_BAD_BUFFER_SIZE; + } + +- // Pick P30_MAX_BUFFER_SIZE_IN_BYTES (== 128 bytes) as a good start for word +- // operations as opposed to erasing the block and writing the data regardless +- // if an erase is really needed. It looks like most individual NV variable +- // writes are smaller than 128 bytes. +- // 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. ++ // Pick 4 * P30_MAX_BUFFER_SIZE_IN_BYTES (== 512 bytes) as a good ++ // start for word operations as opposed to erasing the block and ++ // writing the data regardless if an erase is really needed. ++ // ++ // Many NV variable updates are small enough for a a single ++ // P30_MAX_BUFFER_SIZE_IN_BYTES block write. In case the update is ++ // larger than a single block, or the update crosses a ++ // P30_MAX_BUFFER_SIZE_IN_BYTES boundary (as shown in the diagram ++ // below), or both, we might have to write two or more blocks. + // + // 0 128 256 + // [----------------|----------------] +@@ -578,7 +580,7 @@ NorFlashWriteSingleBlock ( + 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)) { ++ if ((End - Start) <= (4 * 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. +-- +2.39.3 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch b/edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch new file mode 100644 index 0000000..bcf19d2 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch @@ -0,0 +1,111 @@ +From ef99dec08d51bad7be0f84942443a8a0e1412c87 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:01 +0100 +Subject: [PATCH 2/6] OvmfPkg/VirtNorFlashDxe: clarify block write logic & fix + shadowbuffer reads + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 52: OvmfPkg/VirtNorFlashDxe: backport more fixes. +RH-Jira: RHEL-20963 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina +RH-Commit: [2/6] e2f2231fd1b7b702aa5372e790c1d2c06ca79f74 (kraxel.rh/centos-src-edk2) + +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 +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-3-kraxel@redhat.com> +(cherry picked from commit 35d8ea8097794b522149688b5cfaf8364bc44d54) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 36 ++++++++++++++++++++------ + 1 file changed, 28 insertions(+), 8 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 7f4743b003..88a4d2c23f 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,28 @@ 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 & 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. ++ // | | ++ // | 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 +587,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 +623,7 @@ NorFlashWriteSingleBlock ( + + Status = NorFlashWriteBuffer ( + Instance, +- BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS), ++ BlockAddress + Start, + P30_MAX_BUFFER_SIZE_IN_BYTES, + Instance->ShadowBuffer + ); +@@ -609,12 +631,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.39.3 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch b/edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch new file mode 100644 index 0000000..d2e062d --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch @@ -0,0 +1,132 @@ +From 0429352edb21bd20b8192aec3f484361f4dc3b33 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:05 +0100 +Subject: [PATCH 6/6] OvmfPkg/VirtNorFlashDxe: move DoErase code block into new + function + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 52: OvmfPkg/VirtNorFlashDxe: backport more fixes. +RH-Jira: RHEL-20963 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina +RH-Commit: [6/6] 9a25dbbd0d9881664f8ce30efb95c63099785204 (kraxel.rh/centos-src-edk2) + +Move the DoErase code block into a separate function, call the function +instead of jumping around with goto. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20240116171105.37831-7-kraxel@redhat.com> +Reviewed-by: Laszlo Ersek +(cherry picked from commit b481b00f593ef37695ee14271453320ed02a1256) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 76 ++++++++++++++++++-------- + 1 file changed, 52 insertions(+), 24 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 3d1d20daa1..e6aaed27ce 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -502,6 +502,38 @@ NorFlashRead ( + return EFI_SUCCESS; + } + ++STATIC ++EFI_STATUS ++NorFlashWriteSingleBlockWithErase ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN OUT UINTN *NumBytes, ++ IN UINT8 *Buffer ++ ) ++{ ++ EFI_STATUS Status; ++ ++ // Read NOR Flash data into shadow buffer ++ Status = NorFlashReadBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer); ++ if (EFI_ERROR (Status)) { ++ // Return one of the pre-approved error statuses ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // Put the data at the appropriate location inside the buffer area ++ CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes); ++ ++ // Write the modified buffer back to the NorFlash ++ Status = NorFlashWriteBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer); ++ if (EFI_ERROR (Status)) { ++ // Return one of the pre-approved error statuses ++ return EFI_DEVICE_ERROR; ++ } ++ ++ return EFI_SUCCESS; ++} ++ + /* + Write a full or portion of a block. It must not span block boundaries; that is, + Offset + *NumBytes <= Instance->BlockSize. +@@ -607,7 +639,14 @@ NorFlashWriteSingleBlock ( + // that we want to set. In that case, we will need to erase the block first. + for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) { + if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) { +- goto DoErase; ++ Status = NorFlashWriteSingleBlockWithErase ( ++ Instance, ++ Lba, ++ Offset, ++ NumBytes, ++ Buffer ++ ); ++ return Status; + } + + OrigData[CurOffset] = Buffer[CurOffset]; +@@ -636,33 +675,22 @@ NorFlashWriteSingleBlock ( + goto Exit; + } + } +- +-Exit: +- // Put device back into Read Array mode +- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); +- ++ } else { ++ Status = NorFlashWriteSingleBlockWithErase ( ++ Instance, ++ Lba, ++ Offset, ++ NumBytes, ++ Buffer ++ ); + return Status; + } + +-DoErase: +- // Read NOR Flash data into shadow buffer +- Status = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); +- if (EFI_ERROR (Status)) { +- // Return one of the pre-approved error statuses +- return EFI_DEVICE_ERROR; +- } +- +- // Put the data at the appropriate location inside the buffer area +- CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes); +- +- // Write the modified buffer back to the NorFlash +- Status = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); +- if (EFI_ERROR (Status)) { +- // Return one of the pre-approved error statuses +- return EFI_DEVICE_ERROR; +- } ++Exit: ++ // Put device back into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); + +- return EFI_SUCCESS; ++ return Status; + } + + EFI_STATUS +-- +2.39.3 + diff --git a/edk2.spec b/edk2.spec index 9785da9..ab79214 100644 --- a/edk2.spec +++ b/edk2.spec @@ -20,7 +20,7 @@ ExclusiveArch: x86_64 aarch64 Name: edk2 Version: %{GITDATE} -Release: 3%{?dist} +Release: 4%{?dist} Summary: UEFI firmware for 64-bit virtual machines License: BSD-2-Clause-Patent and Apache-2.0 and MIT URL: http://www.tianocore.org @@ -90,6 +90,18 @@ Patch35: edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch Patch36: edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch # For RHEL-21155 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-9] Patch37: edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch +# For RHEL-20963 - [rhel9] guest fails to boot due to ASSERT error +Patch38: edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch +# For RHEL-20963 - [rhel9] guest fails to boot due to ASSERT error +Patch39: edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch +# For RHEL-20963 - [rhel9] guest fails to boot due to ASSERT error +Patch40: edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch +# For RHEL-20963 - [rhel9] guest fails to boot due to ASSERT error +Patch41: edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch +# For RHEL-20963 - [rhel9] guest fails to boot due to ASSERT error +Patch42: edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch +# For RHEL-20963 - [rhel9] guest fails to boot due to ASSERT error +Patch43: edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch # python3-devel and libuuid-devel are required for building tools. # python3-devel is also needed for varstore template generation and @@ -423,6 +435,16 @@ install -m 0644 \ %changelog +* Wed Jan 31 2024 Miroslav Rezanina - 20231122-4 +- edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch [RHEL-20963] +- edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch [RHEL-20963] +- edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch [RHEL-20963] +- edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch [RHEL-20963] +- edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch [RHEL-20963] +- edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch [RHEL-20963] +- Resolves: RHEL-20963 + ([rhel9] guest fails to boot due to ASSERT error) + * Mon Jan 22 2024 Miroslav Rezanina - 20231122-3 - edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch [RHEL-21155] - edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch [RHEL-21155]