Author: oxygene
Date: 2008-09-30 11:42:37 +0200 (Tue, 30 Sep 2008)
New Revision: 70

Modified:
   trunk/filo/fs/fat.h
   trunk/filo/fs/fsys_fat.c
Log:
take a closer look at the filesystem before interpreting it as FAT.

fixes #1

Modified: trunk/filo/fs/fat.h
===================================================================
--- trunk/filo/fs/fat.h 2008-09-29 17:47:50 UTC (rev 69)
+++ trunk/filo/fs/fat.h 2008-09-30 09:42:37 UTC (rev 70)
@@ -1,6 +1,7 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
  *  Copyright (C) 2001  Free Software Foundation, Inc.
+ *  Copyright (C) 2008  coresystems GmbH
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -30,6 +31,35 @@
 typedef __signed__ int __s32;
 typedef unsigned int __u32;
 
+
+struct fat16_extended_bpb {
+       __u8    drive_number;   /* Physical Drive Number */
+       __u8    reserved;       /* "current head" */
+       __u8    boot_signature; /* Extended Boot Signature 0x28 or 0x29 */
+       __u8    id[4];          /* ID (serial number) */
+       __u8    volumelabel[11];/* volume label */
+       __s8    type[8];        /* Padded with blanks: "FAT12", "FAT16" */
+} __attribute__((packed));
+
+struct fat32_extended_bpb {
+       /* The following fields are only used by FAT32 */
+       __u32   fat32_length;   /* sectors/FAT */
+       __u16   flags;          /* bit 8: fat mirroring, low 4: active fat */
+       __u8    version[2];     /* major, minor filesystem version */
+       __u32   root_cluster;   /* first cluster in root directory */
+       __u16   info_sector;    /* filesystem info sector */
+       __u16   backup_boot;    /* backup boot sector */
+       __u16   reserved2[12];  /* Reserved */
+       /* from here on it looks like the fat12/fat16 code */
+       __u8    drive_number;   /* Physical Drive Number */
+       __u8    reserved;       /* "current head" */
+       __u8    boot_signature; /* Extended Boot Signature 0x28 or 0x29 */
+       __u8    id[4];          /* ID (serial number) */
+       __u8    volumelabel[11];/* volume label */
+       __s8    type[8];        /* Padded with blanks: "FAT32" */
+} __attribute__((packed));
+
+
 /* Note that some shorts are not aligned, and must therefore
  * be declared as array of two bytes.
  */
@@ -50,14 +80,10 @@
        __u32   hidden;         /* hidden sectors (unused) */
        __u32   long_sectors;   /* number of sectors (if short_sectors == 0) */
 
-       /* The following fields are only used by FAT32 */
-       __u32   fat32_length;   /* sectors/FAT */
-       __u16   flags;          /* bit 8: fat mirroring, low 4: active fat */
-       __u8    version[2];     /* major, minor filesystem version */
-       __u32   root_cluster;   /* first cluster in root directory */
-       __u16   info_sector;    /* filesystem info sector */
-       __u16   backup_boot;    /* backup boot sector */
-       __u16   reserved2[6];   /* Unused */
+       union {
+               struct fat16_extended_bpb fat16;
+               struct fat32_extended_bpb fat32;
+       } extended;
 };
 
 #define FAT_CVT_U16(bytarr) (* (__u16*)(bytarr))

Modified: trunk/filo/fs/fsys_fat.c
===================================================================
--- trunk/filo/fs/fsys_fat.c    2008-09-29 17:47:50 UTC (rev 69)
+++ trunk/filo/fs/fsys_fat.c    2008-09-30 09:42:37 UTC (rev 70)
@@ -83,7 +83,7 @@
   /* FAT offset and length */
   FAT_SUPER->fat_offset = FAT_CVT_U16 (bpb.reserved_sects);
   FAT_SUPER->fat_length = 
-    bpb.fat_length ? bpb.fat_length : bpb.fat32_length;
+    bpb.fat_length ? bpb.fat_length : bpb.extended.fat32.fat32_length;
   
   /* Rootdir offset and length for FAT12/16 */
   FAT_SUPER->root_offset = 
@@ -99,23 +99,31 @@
         / bpb.sects_per_clust);
   FAT_SUPER->sects_per_clust = bpb.sects_per_clust;
   
+  if (strncmp(bpb.extended.fat16.type, "FAT12", 5) &&
+       strncmp(bpb.extended.fat16.type, "FAT16", 5) &&
+       strncmp(bpb.extended.fat32.type, "FAT32", 5))
+    {
+      /* None of them matched. Bail out */
+      return 0;
+    }
+
   if (!bpb.fat_length)
     {
       /* This is a FAT32 */
       if (FAT_CVT_U16(bpb.dir_entries))
        return 0;
       
-      if (bpb.flags & 0x0080)
+      if (bpb.extended.fat32.flags & 0x0080)
        {
          /* FAT mirroring is disabled, get active FAT */
-         int active_fat = bpb.flags & 0x000f;
+         int active_fat = bpb.extended.fat32.flags & 0x000f;
          if (active_fat >= bpb.num_fats)
            return 0;
          FAT_SUPER->fat_offset += active_fat * FAT_SUPER->fat_length;
        }
       
       FAT_SUPER->fat_size = 8;
-      FAT_SUPER->root_cluster = bpb.root_cluster;
+      FAT_SUPER->root_cluster = bpb.extended.fat32.root_cluster;
 
       /* Yes the following is correct.  FAT32 should be called FAT28 :) */
       FAT_SUPER->clust_eof_marker = 0xffffff8;


--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to