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 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel