aboutsummaryrefslogtreecommitdiff
path: root/shared/fs/fat32/write/boot.zig
blob: b7bc45976810da176ee9190286175109785b629f (plain)
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);
    }
}