:: commit 9174a241dc66a6e596b73777a5cc86e919edfa3d

mintsuki <mintsuki@protonmail.com> — 2021-05-11 04:04

parents: e228745e5c

fat: Implement FAT12

diff --git a/stage23/fs/fat32.s2.c b/stage23/fs/fat32.s2.c
index 13ceb7a6..fe750d71 100644
--- a/stage23/fs/fat32.s2.c
+++ b/stage23/fs/fat32.s2.c
@@ -13,6 +13,7 @@
 #define FAT32_VALID_SIGNATURE_2 0x29
 #define FAT32_VALID_SYSTEM_IDENTIFIER "FAT32   "
 #define FAT16_VALID_SYSTEM_IDENTIFIER "FAT16   "
+#define FAT12_VALID_SYSTEM_IDENTIFIER "FAT12   "
 #define FAT32_SECTOR_SIZE 512
 #define FAT32_ATTRIBUTE_SUBDIRECTORY 0x10
 #define FAT32_LFN_ATTRIBUTE 0x0F
@@ -86,6 +87,11 @@ static int fat32_init_context(struct fat32_context* context, struct volume *part
         goto valid;
     }
 
+    if (strncmp((((void *)&bpb) + 0x36), FAT12_VALID_SYSTEM_IDENTIFIER, SIZEOF_ARRAY(bpb.system_identifier)) == 0) {
+        context->type = 12;
+        goto valid;
+    }
+
     return 1;
 
 valid:
@@ -100,6 +106,7 @@ valid:
     context->root_start = context->reserved_sectors + context->number_of_fats * context->sectors_per_fat;
     context->root_size = DIV_ROUNDUP(context->root_entries * sizeof(struct fat32_directory_entry), FAT32_SECTOR_SIZE);
     switch (context->type) {
+        case 12:
         case 16:
             context->data_start_lba = context->root_start + context->root_size;
             break;
@@ -115,6 +122,17 @@ valid:
 
 static int read_cluster_from_map(struct fat32_context *context, uint32_t cluster, uint32_t *out) {
     switch (context->type) {
+        case 12: {
+            *out = 0;
+            uint16_t tmp = 0;
+            volume_read(context->part, &tmp, context->fat_start_lba * FAT32_SECTOR_SIZE + (cluster + cluster / 2), sizeof(uint16_t));
+            if (cluster % 2 == 0) {
+                *out = tmp & 0xfff;
+            } else {
+                *out = tmp >> 4;
+            }
+            break;
+        }
         case 16:
             *out = 0;
             volume_read(context->part, out, context->fat_start_lba * FAT32_SECTOR_SIZE + cluster * sizeof(uint16_t), sizeof(uint16_t));
@@ -133,7 +151,8 @@ static int read_cluster_from_map(struct fat32_context *context, uint32_t cluster
 static uint32_t *cache_cluster_chain(struct fat32_context *context,
                                      uint32_t initial_cluster,
                                      size_t *_chain_length) {
-    uint32_t cluster_limit = (context->type == 16 ? 0xffef    : 0)
+    uint32_t cluster_limit = (context->type == 12 ? 0xfef     : 0)
+                           | (context->type == 16 ? 0xffef    : 0)
                            | (context->type == 32 ? 0xfffffef : 0);
     if (initial_cluster < 0x2 || initial_cluster > cluster_limit)
         return NULL;
@@ -321,6 +340,7 @@ int fat32_open(struct fat32_file_handle* ret, struct volume *part, const char* p
 
     // walk down the directory tree
     switch (context.type) {
+        case 12:
         case 16:
             current_directory = NULL;
             break;
tab: 248 wrap: offon