Hello again bugs@

Problem: EFIBOOT from removable disk fails to load kernel.
Will succeed eventually after 1 to 15 tries.

Example: 1) Wrote install59.fs to USB flash drive.
         2) Boot UEFI mode.
         3) boot> boot hd1a:/bsd
booting hd1a:/bsd 6838420read text: Unknown error: code 255
 failed(255). will try /bsd

         4) boot> boot hd1a:/bsd
         5) Repeat 4).

After much digging I narrowed the problem to efid_io()
Instrumented with printf() I saw failure occur at random LBA.
EFI_STATUS returned from EFI_CALL() is EFI_NO_RESPONSE.

My thoughts are this problem is caused by crummy UEFI firmware.
I wrote patch to retry reading blocks if status indicates EFI_NO_RESPONSE.

Now booting successfully first try every time. Message occurs 1 to 5 times
every boot. Each time once at different LBA.

Index: efidev.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/efidev.c,v
retrieving revision 1.16
diff -u -p -r1.16 efidev.c
--- efidev.c    6 Jan 2016 02:10:03 -0000       1.16
+++ efidev.c    18 Feb 2016 05:22:40 -0000
@@ -110,32 +110,37 @@ efid_io(int rw, efi_diskinfo_t ed, u_int
                                iblksz = ed->blkio->Media->BlockSize;
                        }
                }
-               if (i_lblks > 0) {
-                       status = EFI_CALL(ed->blkio->ReadBlocks,
-                           ed->blkio, ed->mediaid, lba - 1,
-                           ed->blkio->Media->BlockSize, iblk);
-                       if (EFI_ERROR(status))
-                               goto on_eio;
-                       memcpy(buf, iblk + (blks - i_lblks),
-                           i_lblks * DEV_BSIZE);
-               }
-               if (i_nblks > 0) {
-                       status = EFI_CALL(ed->blkio->ReadBlocks,
-                           ed->blkio, ed->mediaid, lba,
-                           ed->blkio->Media->BlockSize * (i_nblks / blks),
-                           buf + (i_lblks * DEV_BSIZE));
-                       if (EFI_ERROR(status))
-                               goto on_eio;
-               }
-               if (i_tblks > 0) {
-                       status = EFI_CALL(ed->blkio->ReadBlocks,
-                           ed->blkio, ed->mediaid, lba + (i_nblks / blks),
-                           ed->blkio->Media->BlockSize, iblk);
-                       if (EFI_ERROR(status))
-                               goto on_eio;
-                       memcpy(buf + (i_lblks + i_nblks) * DEV_BSIZE, iblk,
-                           i_tblks * DEV_BSIZE);
-               }
+
+               do {            
+                       if (i_lblks > 0) {
+                               status = EFI_CALL(ed->blkio->ReadBlocks,
+                                   ed->blkio, ed->mediaid, lba - 1,
+                                   ed->blkio->Media->BlockSize, iblk);
+                               if (EFI_ERROR(status) && status != 
EFI_NO_RESPONSE)
+                                       goto on_eio;
+                               memcpy(buf, iblk + (blks - i_lblks),
+                                   i_lblks * DEV_BSIZE);
+                       }
+                       if (i_nblks > 0) {
+                               status = EFI_CALL(ed->blkio->ReadBlocks,
+                                   ed->blkio, ed->mediaid, lba,
+                                   ed->blkio->Media->BlockSize * (i_nblks / 
blks),
+                                   buf + (i_lblks * DEV_BSIZE));
+                               if (EFI_ERROR(status) && status != 
EFI_NO_RESPONSE)
+                                       goto on_eio;
+                       }
+                       if (i_tblks > 0) {
+                               status = EFI_CALL(ed->blkio->ReadBlocks,
+                                   ed->blkio, ed->mediaid, lba + (i_nblks / 
blks),
+                                   ed->blkio->Media->BlockSize, iblk);
+                               if (EFI_ERROR(status) && status != 
EFI_NO_RESPONSE)
+                                       goto on_eio;
+                               memcpy(buf + (i_lblks + i_nblks) * DEV_BSIZE, 
iblk,
+                                   i_tblks * DEV_BSIZE);
+                       }
+                       if (status == EFI_NO_RESPONSE)
+                               printf("LBA=%u EFI_NO_RESPONSE\n", lba);
+               } while (status == EFI_NO_RESPONSE);
                break;
        case F_WRITE:
                if (ed->blkio->Media->ReadOnly)

Reply via email to