grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/7] biosdisk: restore LBA mode after read/write failures


From: Mihai Moldovan
Subject: [PATCH 2/7] biosdisk: restore LBA mode after read/write failures
Date: Sun, 24 May 2020 13:43:03 +0200

Falling back to the old-style CHS mode after read failures is a valid
error recovery technique, but read failures can just happen. One
prominent example of that is trying to read the (somewhat) inaccessible
end sectors on newer disks with old, buggy system firmware.

Restore LBA access mode after an old-style CHS mode read/write try
again. This might lead to additional read/write operations (in case they
fail again), but also fixes issues like the biosdisk constantly being
unable to read data off sectors that are located behind the (shy of)
8-GB-mark.
---
 grub-core/disk/i386/pc/biosdisk.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/grub-core/disk/i386/pc/biosdisk.c 
b/grub-core/disk/i386/pc/biosdisk.c
index 044bc48f3..3d55e68f8 100644
--- a/grub-core/disk/i386/pc/biosdisk.c
+++ b/grub-core/disk/i386/pc/biosdisk.c
@@ -990,11 +990,27 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
             * sectors, fall back to the CHS mode ...
             */
            grub_err_t chs_read = GRUB_ERR_NONE;
+
+           /* Save old data first. */
+           grub_uint64_t old_total_sectors = disk->total_sectors;
+
+           /*
+            * Switch into CHS mode and call the old-style reading code path.
+            */
            data->flags &= ~GRUB_BIOSDISK_FLAG_LBA;
            disk->total_sectors = data->cylinders * data->heads * data->sectors;
-
            chs_read = grub_biosdisk_rw (cmd, disk, sector, size, segment);
 
+           /*
+            * Whatever happened, restore LBA access.
+            *
+            * We don't want the biosdisk instance to permanently degrade into
+            * an old-style CHS access mode after a read failure. Read failures
+            * can happen, especially for the end sectors.
+            */
+           data->flags |= GRUB_BIOSDISK_FLAG_LBA;
+           disk->total_sectors = old_total_sectors;
+
            /* Pass CHS operation result through. */
            return chs_read;
          }
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]