From e90b72ec3082588b296956730bd2930cf8d5d671 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Fri, 10 Jul 2026 11:31:46 +0800 Subject: refactor: promote new architecture to repository root Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior. --- src/fs/fat32.cc | 806 -------------------------------------------------------- 1 file changed, 806 deletions(-) delete mode 100644 src/fs/fat32.cc (limited to 'src/fs/fat32.cc') diff --git a/src/fs/fat32.cc b/src/fs/fat32.cc deleted file mode 100644 index e4089d4..0000000 --- a/src/fs/fat32.cc +++ /dev/null @@ -1,806 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2026 Richard QIn - */ -#include "fs/fat32.h" -#include "lib/string.h" -#include "drivers/uart.h" -#include "kernel/mm.h" -#include "kernel/proc.h" - -FAT32FileSystem fat32_fs; - -// Helper function -static void generate_short_name(char *dst, const char *src) -{ - memset(dst, ' ', 11); - - int i = 0; - for (; *src && *src != '.' && i < 8; src++) - { - char c = *src; - if (c >= 'a' && c <= 'z') - c -= 32; - dst[i++] = c; - } - - while (*src && *src != '.') - src++; - if (*src == '.') - src++; - - i = 8; - for (; *src && i < 11; src++) - { - char c = *src; - if (c >= 'a' && c <= 'z') - c -= 32; - dst[i++] = c; - } -} - -// FAT32 FileSystem Implementation - -void FAT32FileSystem::init() -{ - struct Buf *b = BufferCache::bread(0, 0); - uint8 *data = (uint8 *)b->data; - struct FAT32_BPB *bpb = (struct FAT32_BPB *)data; - - uint32 partition_lba = 0; - - bool is_valid_bpb = (bpb->bytesPerSector == 512) && (bpb->rootClus != 0); - - if (!is_valid_bpb) - { - Drivers::uart_puts("[FAT32] Sector 0 is not a valid BPB. Checking MBR...\n"); - - if (data[510] != 0x55 || data[511] != 0xAA) - { - Drivers::uart_puts("[FAT32] Panic: Invalid Disk Signature!\n"); - while (1) - ; - } - - uint32 lba = *(uint32 *)(data + 446 + 8); - - if (lba > 0) - { - Drivers::uart_puts("[FAT32] MBR Partition 1 found @ Sector "); - Drivers::uart_put_int(lba); - Drivers::uart_puts("\n"); - partition_lba = lba; - } - else - { - Drivers::uart_puts("[FAT32] Panic: No partition found.\n"); - while (1) - ; - } - - BufferCache::brelse(b); - - b = BufferCache::bread(0, partition_lba / 2); - bpb = (struct FAT32_BPB *)b->data; - } - - if (bpb->bytesPerSector != 512) - { - Drivers::uart_puts("[FAT32] Panic: Invalid FAT32 BPB in partition.\n"); - while (1) - ; - } - - uint32 fat_sz = bpb->FATSz32; - this->fat_sz = fat_sz; - uint32 reserved_sec = bpb->reservedSecCnt; - uint8 num_fats = bpb->numFATs; - - sectors_per_cluster = bpb->secPerClus; - bytes_per_cluster = sectors_per_cluster * 512; - root_cluster = bpb->rootClus; - - fat_start_sector = partition_lba + reserved_sec; - data_start_sector = partition_lba + reserved_sec + (fat_sz * num_fats); - - Drivers::uart_puts(ANSI_GREEN); - Drivers::uart_puts("[FAT32] Init Success: RootClus="); - Drivers::uart_put_int(root_cluster); - Drivers::uart_puts(", DataStart="); - Drivers::uart_put_int(data_start_sector); - Drivers::uart_puts(ANSI_RESET); - Drivers::uart_puts("\n"); - - BufferCache::brelse(b); -} - -Inode *FAT32FileSystem::root() -{ - FAT32Inode *ip = new FAT32Inode(); - - ip->fs = this; - ip->dev = 0; - ip->inum = root_cluster; - ip->ref_cnt = 1; - ip->valid = 1; - ip->type = T_DIR; - ip->size = 0; - ip->nlink = 1; - - ip->first_clus = root_cluster; - ip->parent_clus = 0; - - return ip; -} - -uint32 FAT32FileSystem::cluster_to_sector(uint32 cluster) -{ - return data_start_sector + (cluster - 2) * sectors_per_cluster; -} - -uint32 FAT32FileSystem::next_cluster(uint32 cluster) -{ - uint32 fat_offset = cluster * 4; - uint32 fat_sector = fat_start_sector + (fat_offset / 512); - uint32 ent_offset = fat_offset % 512; - - // block = sector / 2 - struct Buf *b = BufferCache::bread(0, fat_sector / 2); - - uint32 block_offset = (fat_sector % 2) * 512 + ent_offset; - uint32 next = *(uint32 *)(b->data + block_offset); - - BufferCache::brelse(b); - - return next & 0x0FFFFFFF; -} - -// FAT32 Inode Implementation - -static bool match_name(const char *disk_name, const char *target) -{ - char temp[13]; - int i, j; - - for (i = 0; i < 8 && disk_name[i] != ' '; i++) - temp[i] = disk_name[i]; - if (disk_name[8] != ' ') - { - temp[i++] = '.'; - for (j = 0; j < 3 && disk_name[8 + j] != ' '; j++) - temp[i++] = disk_name[8 + j]; - } - temp[i] = 0; - return strcasecmp(temp, target) == 0; -} - -int FAT32Inode::read(char *dst, uint32 off, uint32 n, int isUser) -{ - if (first_clus == 0) - return 0; - - // [FIX] 只有非目录文件才检查 size 边界 - // 目录文件 size 可能为 0,应允许读取直到簇链结束 - if (type != T_DIR) - { - if (off >= size) - { - return 0; - } - if (off + n > size) - { - n = size - off; - } - } - - uint32 tot = 0; - uint32 clus = first_clus; - uint32 clus_sz = fs->bytes_per_cluster; - - uint32 skip = off / clus_sz; - uint32 current_off = off % clus_sz; - - while (skip > 0) - { - clus = fs->next_cluster(clus); - if (clus >= 0x0FFFFFF8) - return 0; - skip--; - } - - while (tot < n) - { - uint32 sec_in_clus = current_off / 512; - - if (sec_in_clus >= fs->sectors_per_cluster) - { - clus = fs->next_cluster(clus); - if (clus >= 0x0FFFFFF8) - break; - current_off = 0; - continue; - } - - uint32 sec = fs->cluster_to_sector(clus) + sec_in_clus; - uint32 off_in_sec = current_off % 512; - - uint32 m = 512 - off_in_sec; - if (n - tot < m) - m = n - tot; - - struct Buf *b = BufferCache::bread(dev, sec / 2); - uint32 block_offset = (sec % 2) * 512 + off_in_sec; - - if (isUser) - { - if (VM::copyout(myproc()->pagetable, (uint64)dst, (char *)(b->data + block_offset), m) < 0) - { - BufferCache::brelse(b); - return -1; - } - } - else - { - memmove(dst, b->data + block_offset, m); - } - BufferCache::brelse(b); - - tot += m; - dst += m; - current_off += m; - } - return tot; -} - -Inode *FAT32Inode::lookup(const char *name) -{ - if (type != T_DIR) - return nullptr; - - uint32 clus = first_clus; - struct FAT32_DirEnt de; - - while (clus < 0x0FFFFFF8) - { - uint32 sec = fs->cluster_to_sector(clus); - - for (uint32 i = 0; i < fs->sectors_per_cluster; i++) - { - uint32 current_sec = sec + i; - struct Buf *b = BufferCache::bread(dev, current_sec / 2); - uint32 block_base = (current_sec % 2) * 512; - - for (int off = 0; off < 512; off += 32) - { - memmove(&de, b->data + block_base + off, 32); - - if (de.name[0] == 0x00) - { - BufferCache::brelse(b); - return nullptr; - } - if (de.name[0] == 0xE5) - continue; - if (de.attr & ATTR_LONG_NAME) - continue; - - if (match_name(de.name, name)) - { - FAT32Inode *ip = new FAT32Inode(); - ip->fs = fs; - ip->dev = dev; - ip->type = (de.attr & ATTR_DIRECTORY) ? T_DIR : T_FILE; - ip->size = de.fileSize; - ip->first_clus = (de.fstClusHI << 16) | de.fstClusLO; - ip->inum = ip->first_clus; - ip->nlink = 1; - ip->ref_cnt = 1; - ip->valid = 1; - ip->ent_sec = current_sec; // Log Sector - ip->ent_off = off; // Log Setoff - - BufferCache::brelse(b); - return ip; - } - } - BufferCache::brelse(b); - } - clus = fs->next_cluster(clus); - } - return nullptr; -} - -// Placeholder -uint32 FAT32FileSystem::alloc_cluster() -{ - uint32 fat_entries_per_sector = 512 / 4; - for (uint32 i = 0; i < fat_sz; i++) - { - uint32 current_fat_sec = fat_start_sector + i; - struct Buf *b = BufferCache::bread(0, current_fat_sec / 2); - uint32 *table = (uint32 *)(b->data + (current_fat_sec % 2) * 512); - for (uint32 j = 0; j < fat_entries_per_sector; j++) - { - if (i == 0 && j < 2) - continue; - - if ((table[j] & 0x0FFFFFFF) == 0) - { - // Find the free cluster and mark it as EOF (0x0FFFFFFF) - table[j] = 0x0FFFFFFF; - BufferCache::bwrite(b); // Write back to disk - BufferCache::brelse(b); - - uint32 cluster_idx = i * fat_entries_per_sector + j; - - // Clear the data content of the new cluster - uint32 data_sec = cluster_to_sector(cluster_idx); - for (uint32 k = 0; k < sectors_per_cluster; k++) - { - struct Buf *db = BufferCache::bread(0, (data_sec + k) / 2); - memset(db->data + ((data_sec + k) % 2) * 512, 0, 512); - BufferCache::bwrite(db); - BufferCache::brelse(db); - } - - return cluster_idx; - } - } - BufferCache::brelse(b); - } - Drivers::uart_puts("[FAT32] Out of space!\n"); - return 0; -} - -void FAT32FileSystem::free_cluster_chain(uint32 cluster) -{ - while (cluster >= 2 && cluster < 0x0FFFFFF8) - { - uint32 next = next_cluster(cluster); - - // Calculate the current cluster's position in the FAT table - uint32 fat_offset = cluster * 4; - uint32 fat_sector = fat_start_sector + (fat_offset / 512); - uint32 ent_offset = fat_offset % 512; - - // Read FAT sector - struct Buf *b = BufferCache::bread(0, fat_sector / 2); - - // Marked as idle (0x00000000) - uint32 *entry = (uint32 *)(b->data + (fat_sector % 2) * 512 + ent_offset); - *entry = 0; - - BufferCache::bwrite(b); - BufferCache::brelse(b); - - cluster = next; - } -} - -void FAT32Inode::update() -{ - struct Buf *b = BufferCache::bread(dev, ent_sec / 2); - uint32 offset = (ent_sec % 2) * 512 + ent_off; - - struct FAT32_DirEnt *de = (struct FAT32_DirEnt *)(b->data + offset); - - // Update file size and starting cluster - de->fileSize = size; - de->fstClusHI = (uint16)((first_clus >> 16) & 0xFFFF); - de->fstClusLO = (uint16)(first_clus & 0xFFFF); - - BufferCache::bwrite(b); - BufferCache::brelse(b); -} - -int FAT32Inode::write(const char *src, uint32 off, uint32 n, int isUser) -{ - if (off > size) - { - return -1; - } - - uint32 tot = 0; - uint32 clus = first_clus; - uint32 clus_sz = fs->bytes_per_cluster; - uint32 prev_clus = 0; - - if (clus == 0) - { - clus = fs->alloc_cluster(); - if (clus == 0) - return -1; - first_clus = clus; - // Update the metadata immediately to prevent data loss in case of a power outage. - update(); - } - - uint32 skip = off / clus_sz; - uint32 current_off = off % clus_sz; - - while (skip > 0) - { - prev_clus = clus; - clus = fs->next_cluster(clus); - if (clus >= 0x0FFFFFF8) - { - return -1; - } - skip--; - } - while (tot < n) - { - if (current_off == clus_sz) - { - uint32 next = fs->next_cluster(clus); - if (next >= 0x0FFFFFF8) - { - uint32 new_clus = fs->alloc_cluster(); - if (new_clus == 0) - break; - - // Point the current cluster to the new cluster (update the FAT table) - uint32 fat_offset = clus * 4; - uint32 fat_sec = fs->fat_start_sector + (fat_offset / 512); - struct Buf *fat_b = BufferCache::bread(dev, fat_sec / 2); - uint32 *entry = (uint32 *)(fat_b->data + (fat_sec % 2) * 512 + (fat_offset % 512)); - *entry = new_clus; // Link - BufferCache::bwrite(fat_b); - BufferCache::brelse(fat_b); - - clus = new_clus; - } - else - { - clus = next; - } - current_off = 0; - } - - // Calculate the physical sector to write - uint32 sec_in_clus = current_off / 512; - uint32 sec = fs->cluster_to_sector(clus) + sec_in_clus; - uint32 off_in_sec = current_off % 512; - - // Calculate how many bytes can be written this time - uint32 m = 512 - off_in_sec; - if (n - tot < m) - m = n - tot; - - struct Buf *b = BufferCache::bread(dev, sec / 2); - uint32 block_offset = (sec % 2) * 512 + off_in_sec; - - if (isUser) - { - if (VM::copyin(myproc()->pagetable, (char *)(b->data + block_offset), (uint64)src, m) < 0) - { - BufferCache::brelse(b); - return -1; - } - } - else - { - memmove(b->data + block_offset, src, m); - } - - BufferCache::bwrite(b); - BufferCache::brelse(b); - - tot += m; - src += m; - current_off += m; - } - if (off + n > size) - { - size = off + n; - update(); - } - - return tot; -} - -Inode *FAT32Inode::create(const char *name, short type, short major, short minor) -{ - Inode *exist = lookup(name); - if (exist) - { - return exist; - } - - struct FAT32_DirEnt de; - memset(&de, 0, sizeof(de)); - generate_short_name(de.name, name); - de.attr = (type == T_DIR) ? ATTR_DIRECTORY : ATTR_ARCHIVE; - - uint32 new_dir_clus = 0; - if (type == T_DIR) - { - new_dir_clus = fs->alloc_cluster(); - if (new_dir_clus == 0) - return nullptr; - - de.fstClusHI = (uint16)((new_dir_clus >> 16) & 0xFFFF); - de.fstClusLO = (uint16)(new_dir_clus & 0xFFFF); - } - else - { - de.fileSize = 0; - } - - uint32 clus = first_clus; - bool written = false; - - while (true) - { - uint32 sec = fs->cluster_to_sector(clus); - - for (uint32 i = 0; i < fs->sectors_per_cluster; i++) - { - struct Buf *b = BufferCache::bread(dev, (sec + i) / 2); - uint8 *data = (uint8 *)b->data + ((sec + i) % 2) * 512; - - for (int off = 0; off < 512; off += 32) - { - if (data[off] == 0x00 || data[off] == 0xE5) - { - memmove(data + off, &de, 32); - BufferCache::bwrite(b); - BufferCache::brelse(b); - written = true; - break; - } - } - - if (written) - break; - BufferCache::brelse(b); - } - - if (written) - break; - - uint32 next = fs->next_cluster(clus); - if (next >= 0x0FFFFFF8) - { - uint32 new_parent_clus = fs->alloc_cluster(); - if (new_parent_clus == 0) - return nullptr; - - uint32 fat_off = clus * 4; - uint32 fat_sec = fs->fat_start_sector + (fat_off / 512); - struct Buf *fb = BufferCache::bread(dev, fat_sec / 2); - *(uint32 *)(fb->data + (fat_sec % 2) * 512 + (fat_off % 512)) = new_parent_clus; - BufferCache::bwrite(fb); - BufferCache::brelse(fb); - - uint32 s = fs->cluster_to_sector(new_parent_clus); - for (uint32 k = 0; k < fs->sectors_per_cluster; k++) - { - struct Buf *zb = BufferCache::bread(dev, (s + k) / 2); - uint8 *zdata = (uint8 *)zb->data + ((s + k) % 2) * 512; - memset(zdata, 0, 512); - - if (k == 0) - { - memmove(zdata, &de, 32); - } - - BufferCache::bwrite(zb); - BufferCache::brelse(zb); - } - - written = true; - break; - } - clus = next; - } - - if (written && type == T_DIR) - { - struct FAT32_DirEnt dot; - memset(&dot, 0, 32); - memset(dot.name, ' ', 11); - dot.name[0] = '.'; - dot.attr = ATTR_DIRECTORY; - dot.fstClusHI = (uint16)((new_dir_clus >> 16) & 0xFFFF); - dot.fstClusLO = (uint16)(new_dir_clus & 0xFFFF); - - struct FAT32_DirEnt dotdot; - memset(&dotdot, 0, 32); - memset(dotdot.name, ' ', 11); - dotdot.name[0] = '.'; - dotdot.name[1] = '.'; - dotdot.attr = ATTR_DIRECTORY; - - uint32 parent_clus_num = this->first_clus; - if (parent_clus_num == fs->root_cluster) - { - parent_clus_num = 0; - } - dotdot.fstClusHI = (uint16)((parent_clus_num >> 16) & 0xFFFF); - dotdot.fstClusLO = (uint16)(parent_clus_num & 0xFFFF); - - uint32 s = fs->cluster_to_sector(new_dir_clus); - - struct Buf *zb = BufferCache::bread(dev, s / 2); - uint8 *zdata = (uint8 *)zb->data + (s % 2) * 512; - - memmove(zdata, &dot, 32); // Offset 0 - memmove(zdata + 32, &dotdot, 32); // Offset 32 - - BufferCache::bwrite(zb); - BufferCache::brelse(zb); - } - - if (written) - { - return lookup(name); - } - - return nullptr; -} - -void FAT32Inode::truncate() -{ - if (first_clus == 0) - { - if (size != 0) - { - size = 0; - update(); - } - return; - } - - fs->free_cluster_chain(first_clus); - - size = 0; - first_clus = 0; - - update(); -} - -int FAT32Inode::unlink(const char *name) -{ - if (type != T_DIR) - return -1; - if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) - return -1; - - uint32_t clus = first_clus; - bool found = false; - - // [FIX] Deadlock prevention: Do not hold buffer while looking up inode - uint32_t target_block = 0; - uint32_t target_offset = 0; - struct FAT32_DirEnt de; - - while (true) - { - uint32_t sec = fs->cluster_to_sector(clus); - for (uint32 i = 0; i < fs->sectors_per_cluster; ++i) - { - struct Buf *b = BufferCache::bread(dev, (sec + i) / 2); - uint8_t *data = (uint8_t *)b->data + ((sec + i) % 2) * 512; - - for (int off = 0; off < 512; off += 32) - { - memmove(&de, data + off, 32); - if (de.name[0] == 0x00) // end of dir - { - BufferCache::brelse(b); - return -1; // Not found - } - if (de.name[0] == 0xE5) - continue; // have been unlink - if (de.attr & ATTR_LONG_NAME) - continue; - - if (match_name(de.name, name)) - { - target_block = (sec + i) / 2; - target_offset = ((sec + i) % 2) * 512 + off; - found = true; - break; - } - } - - BufferCache::brelse(b); // Always release buffer - if (found) - break; - } - - if (found) - break; - - clus = fs->next_cluster(clus); - if (clus >= 0x0FFFFFF8) - return -1; - } - - if (found) - { - Inode *target_ip = lookup(name); - if (target_ip) - { - VFS::ilock(target_ip); - if (target_ip->type == T_DIR) - { - VFS::iunlockput(target_ip); - return -1; - } - - target_ip->nlink--; - target_ip->update(); - VFS::iunlockput(target_ip); - } - - // Re-read buffer to mark deletion - struct Buf *target_buf = BufferCache::bread(dev, target_block); - uint8_t *ptr = (uint8_t *)target_buf->data + target_offset; - *ptr = 0xE5; - - BufferCache::bwrite(target_buf); - BufferCache::brelse(target_buf); - return 0; - } - - return -1; -} - -// Test Function -void fat32_test() -{ - static bool inited = false; - if (!inited) - { - fat32_fs.init(); - inited = true; - } - - Drivers::uart_puts("\n[FAT32] Starting Test via Syscall...\n"); - - Inode *root = fat32_fs.root(); - if (root) - { - Drivers::uart_puts("[FAT32] Root Inode retrieved. Inum: "); - Drivers::uart_put_int(root->inum); - Drivers::uart_puts("\n"); - - Drivers::uart_puts("[FAT32] Looking for TEST.TXT...\n"); - Inode *node = root->lookup("test.txt"); - - if (node) - { - Drivers::uart_puts("[FAT32] Found TEST.TXT! Size: "); - Drivers::uart_put_int(node->size); - Drivers::uart_puts("\n"); - - char buf[128]; - int n = node->read(buf, 0, 127, 0); - if (n > 0) - { - buf[n] = 0; - Drivers::uart_puts("[FAT32] Content:\n>> "); - Drivers::uart_puts(buf); - Drivers::uart_puts("\n"); - } - else - { - Drivers::uart_puts("[FAT32] Read returned 0.\n"); - } - VFS::iput(node); - } - else - { - Drivers::uart_puts("[FAT32] TEST.TXT not found.\n"); - } - VFS::iput(root); - } - else - { - Drivers::uart_puts("[FAT32] Failed to get root inode.\n"); - } - - Drivers::uart_puts("[FAT32] Test Finished.\n"); -} \ No newline at end of file -- cgit v1.2.3