diff mbox series

[U-Boot,1/1] disk: part_dos: correctly detect DOS PBR

Message ID 20191015184342.10530-1-xypron.glpk@gmx.de
State Accepted
Commit 34856b0f1c4e56ad63879b9cdef71302225423cd
Delegated to: Tom Rini
Headers show
Series [U-Boot,1/1] disk: part_dos: correctly detect DOS PBR | expand

Commit Message

Heinrich Schuchardt Oct. 15, 2019, 6:43 p.m. UTC
The signature 0x55 0xAA in bytes 510 and 511 of the first sector can either
indicate a DOS partition table of the first sector of a FAT file system.

The current code tries to check if the partition table is valid by looking
at the boot indicator of the partition entries. But first of all it does
not count from 0 to 3 but only from 0 to 2. And second it misses to
increment the pointer for the partition entry.

If it is a FAT file system can be discovered by looking for the text 'FAT'
at offset 0x36 or 'FAT32' at offset 0x52. In a DOS PBR there are no
partition entries, so those bytes are undefined. Don't require the byte at
offset 0x1BE to differ from 0x00 and 0x80.

With the patch the logic is changed as follows:

If the partition table has either an invalid boot flag for any partition or
has no partition at all, check if the first sector is a DOS PBR by looking
at the FAT* signature.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 disk/part_dos.c | 39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)

--
2.23.0

Comments

Tom Rini Nov. 1, 2019, 1:30 p.m. UTC | #1
On Tue, Oct 15, 2019 at 08:43:42PM +0200, Heinrich Schuchardt wrote:

> The signature 0x55 0xAA in bytes 510 and 511 of the first sector can either
> indicate a DOS partition table of the first sector of a FAT file system.
> 
> The current code tries to check if the partition table is valid by looking
> at the boot indicator of the partition entries. But first of all it does
> not count from 0 to 3 but only from 0 to 2. And second it misses to
> increment the pointer for the partition entry.
> 
> If it is a FAT file system can be discovered by looking for the text 'FAT'
> at offset 0x36 or 'FAT32' at offset 0x52. In a DOS PBR there are no
> partition entries, so those bytes are undefined. Don't require the byte at
> offset 0x1BE to differ from 0x00 and 0x80.
> 
> With the patch the logic is changed as follows:
> 
> If the partition table has either an invalid boot flag for any partition or
> has no partition at all, check if the first sector is a DOS PBR by looking
> at the FAT* signature.
> 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

Applied to u-boot/master, thanks!
diff mbox series

Patch

diff --git a/disk/part_dos.c b/disk/part_dos.c
index 8ddc13b50c..83ff40d310 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -67,28 +67,39 @@  static int test_block_type(unsigned char *buffer)
 {
 	int slot;
 	struct dos_partition *p;
+	int part_count = 0;

 	if((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
 	    (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
 		return (-1);
 	} /* no DOS Signature at all */
 	p = (struct dos_partition *)&buffer[DOS_PART_TBL_OFFSET];
-	for (slot = 0; slot < 3; slot++) {
-		if (p->boot_ind != 0 && p->boot_ind != 0x80) {
-			if (!slot &&
-			    (strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],
-				     "FAT", 3) == 0 ||
-			     strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],
-				     "FAT32", 5) == 0)) {
-				return DOS_PBR; /* is PBR */
-			} else {
-				return -1;
-			}
-		}
+
+	/* Check that the boot indicators are valid and count the partitions. */
+	for (slot = 0; slot < 4; ++slot, ++p) {
+		if (p->boot_ind != 0 && p->boot_ind != 0x80)
+			break;
+		if (p->sys_ind)
+			++part_count;
 	}
-	return DOS_MBR;	    /* Is MBR */
-}

+	/*
+	 * If the partition table is invalid or empty,
+	 * check if this is a DOS PBR
+	 */
+	if (slot != 4 || !part_count) {
+		if (!strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],
+			     "FAT", 3) ||
+		    !strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],
+			     "FAT32", 5))
+			return DOS_PBR; /* This is a DOS PBR and not an MBR */
+	}
+	if (slot == 4)
+		return DOS_MBR;	/* This is an DOS MBR */
+
+	/* This is neither a DOS MBR nor a DOS PBR */
+	return -1;
+}

 static int part_test_dos(struct blk_desc *dev_desc)
 {