1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
//! FAT32 Boot Sector Creation
const std = @import("std");
const constants = @import("../constants/constants.zig");
const types = @import("../types/types.zig");
const BootSector = types.BootSector;
const FsInfo = types.FsInfo;
/// Parameters for creating a FAT32 filesystem
pub const CreateParams = struct {
total_sectors: u32,
hidden_sectors: u32 = 0,
bytes_per_sector: u16 = 512,
sectors_per_cluster: u8 = 1,
reserved_sectors: u16 = 32,
fat_count: u8 = 2,
volume_id: u32 = 0x12345678,
volume_label: [11]u8 = .{ 'N', 'O', ' ', 'N', 'A', 'M', 'E', ' ', ' ', ' ', ' ' },
};
/// Calculate FAT size in sectors
pub fn calculate_fat_size(params: CreateParams) u32 {
const data_sectors = params.total_sectors - params.reserved_sectors;
const cluster_count = data_sectors / params.sectors_per_cluster;
// Each FAT entry is 4 bytes
const fat_bytes = (cluster_count + 2) * 4;
return (fat_bytes + params.bytes_per_sector - 1) / params.bytes_per_sector;
}
/// Create a boot sector structure
pub fn create_boot_sector(params: CreateParams) BootSector {
const fat_size = calculate_fat_size(params);
const boot = BootSector{
.jump_boot = .{ 0xEB, 0x58, 0x90 },
.oem_name = constants.default_oem_name,
.bytes_per_sector = params.bytes_per_sector,
.sectors_per_cluster = params.sectors_per_cluster,
.reserved_sectors = params.reserved_sectors,
.fat_count = params.fat_count,
.root_entry_count = 0,
.total_sectors_16 = 0,
.media_type = constants.default_media_type,
.fat_size_16 = 0,
.sectors_per_track = 63,
.head_count = 255,
.hidden_sectors = params.hidden_sectors,
.total_sectors_32 = params.total_sectors,
.fat_size_32 = fat_size,
.ext_flags = 0,
.fs_version = 0,
.root_cluster = 2,
.fsinfo_sector = 1,
.backup_boot_sector = 6,
.reserved = [_]u8{0} ** 12,
.drive_number = constants.default_drive_number,
.reserved1 = 0,
.boot_sig = constants.default_boot_sig,
.volume_id = params.volume_id,
.volume_label = params.volume_label,
.fs_type = constants.fs_type_fat32,
.boot_code = [_]u8{0} ** 420,
.signature = constants.boot_signature,
};
return boot;
}
/// Create FSInfo structure
pub fn create_fsinfo(free_clusters: u32, next_free: u32) FsInfo {
return FsInfo{
.signature_1 = constants.fsinfo_sig1,
.reserved_1 = [_]u8{0} ** 480,
.signature_2 = constants.fsinfo_sig2,
.free_cluster_count = free_clusters,
.next_free_cluster = next_free,
.reserved_2 = [_]u8{0} ** 12,
.signature_3 = constants.fsinfo_sig3,
};
}
/// Initialize FAT table with required entries
pub fn init_fat_table(fat: []u8) void {
// Clear
@memset(fat, 0);
// Entry 0: Media type
std.mem.writeInt(u32, fat[0..4], 0x0FFFFFF8, .little);
// Entry 1: End of chain marker
std.mem.writeInt(u32, fat[4..8], 0x0FFFFFFF, .little);
// Entry 2: Origin stack EOC
std.mem.writeInt(u32, fat[8..12], 0x0FFFFFFF, .little);
}
/// Allocate a cluster in the FAT
pub fn allocate_cluster(fat: []u8, cluster: u32) void {
const offset = cluster * 4;
if (offset + 4 <= fat.len) {
std.mem.writeInt(u32, fat[offset..][0..4], constants.cluster_eoc, .little);
}
}
/// Link two clusters in the FAT
pub fn link_clusters(fat: []u8, from: u32, to: u32) void {
const offset = from * 4;
if (offset + 4 <= fat.len) {
std.mem.writeInt(u32, fat[offset..][0..4], to, .little);
}
}
|