I recently got a Raspberry Pi 3 Model B Plus (Rev 1.3).  After
installing current the first thing during boot which I get is:

...
starting network
reordering libraries: done.
starting early daemons: syslogd pflogd ntpd.
starting RPC daemons:.
savecore: no core dump
bcmsdhost0: transfer timeout!
Bus error
checking quotas:Bus error
done.
...

The BCM2835 SD controller is always dying just after savecore(8) has
been executed.  My disklabel:

# /dev/rsd0c:
type: SCSI
disk: SCSI disk
label: SD/MMC SD64G
duid: 6f88ece62f92fcb2
flags:
bytes/sector: 512
sectors/track: 63
tracks/cylinder: 255
sectors/cylinder: 16065
cylinders: 7764
total sectors: 124735488
boundstart: 65536
boundend: 124735488
drivedata: 0 

16 partitions:
#                size           offset  fstype [fsize bsize   cpg]
  a:        104871040            65536  4.2BSD   2048 16384 12960 # /
  b:         19798912        104936576    swap                    # none
  c:        124735488                0  unused                    
  i:            32768            32768   MSDOS

At the end when savecore(8) is reading the swap partition, the last read
request has always triggered the SD controller timeout:

DEBUG: sdhsts=0x80, nblks=8, datalen=4096, arg=0x76f4ff8

0x76f4ff8 = 124735480 + 8 = 124735488

So we overwrite the disk offset by 1 block, which in this case made the
SD controller hang.

Some debugging hours later Theo has finally identified that sdmmc_scsi.c
is having an off-by-one bug during the offset out-of-bounds check.

Following patch fixes that, and makes my Raspberry boot up happily.

OK?


Index: sys/dev/sdmmc/sdmmc_scsi.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_scsi.c,v
retrieving revision 1.59
diff -u -p -u -p -r1.59 sdmmc_scsi.c
--- sys/dev/sdmmc/sdmmc_scsi.c  15 Oct 2020 13:22:13 -0000      1.59
+++ sys/dev/sdmmc/sdmmc_scsi.c  23 Mar 2021 07:32:52 -0000
@@ -365,9 +365,8 @@ sdmmc_scsi_cmd(struct scsi_xfer *xs)
        /* A read or write operation. */
        sdmmc_scsi_decode_rw(xs, &blockno, &blockcnt);
 
-       if (blockno >= tgt->card->csd.capacity ||
-           blockno + blockcnt > tgt->card->csd.capacity) {
-               DPRINTF(("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc),
+       if (blockno + blockcnt >= tgt->card->csd.capacity) {
+               DPRINTF(("%s: out of bounds %u+%u >= %u\n", DEVNAME(sc),
                    blockno, blockcnt, tgt->card->csd.capacity));
                xs->error = XS_DRIVER_STUFFUP;
                scsi_done(xs);

Reply via email to