1# -*- coding: utf-8 -*-
2
3"""Boot sector header specific implementation for FAT12/16 and FAT32."""
4
5import struct
6from collections import OrderedDict
7
8
9class BootSectorHeader(OrderedDict):
10 """Base/Interface class for Boot sector header implementation."""
11
12 #: BPB header layout in struct formatted string
13 HEADER_LAYOUT = "<3s8sHBHBHHBHHHLL"
14 #: BPB header fields when extracted with bpb_header_layout
15 HEADER_VARS = ["BS_jmpBoot", "BS_OEMName", "BPB_BytsPerSec",
16 "BPB_SecPerClus", "BPB_RsvdSecCnt", "BPB_NumFATs",
17 "BPB_RootEntCnt", "BPB_TotSec16", "BPB_Media",
18 "BPB_FATSz16", "BPB_SecPerTrk", "BPB_NumHeads",
19 "BPB_HiddSec", "BPB_TotSec32"]
20
21 def __init__(self):
22 """Initialize an empty Boot sector header."""
23 super().__init__()
24 self.update(dict.fromkeys(self.HEADER_VARS))
25
26 def __bytes__(self):
27 """Serialize header data back to bytes."""
28 return struct.pack(self.HEADER_LAYOUT, *self.values())
29
30 def __len__(self):
31 """Return struct size."""
32 return struct.calcsize(self.HEADER_LAYOUT)
33
34 def parse_header(self, data: bytes):
35 """Parse header data from bytes.
36
37 :param data: `bytes`: Raw header data from disk
38 """
39 if len(data) < len(self):
40 raise ValueError(f"Invalid Boot sector header data supplied "
41 f"for {type(self)}. len(data)={len(data)}, "
42 f"len(header)={len(self)}")
43
44 header = struct.unpack(self.HEADER_LAYOUT, data[:len(self)])
45 self.update(dict(zip(self.HEADER_VARS, header)))
46
47
48class FAT12BootSectorHeader(BootSectorHeader):
49 """FAT12/16-specific header implementation."""
50
51 #: FAT12/16 header layout in struct formatted string
52 HEADER_LAYOUT = BootSectorHeader.HEADER_LAYOUT + "BBBL11s8s"
53 #: FAT12/16 header fields when extracted with fat12_header_layout
54 HEADER_VARS = BootSectorHeader.HEADER_VARS + \
55 ["BS_DrvNum", "BS_Reserved1", "BS_BootSig",
56 "BS_VolID", "BS_VolLab", "BS_FilSysType"]
57
58
59class FAT32BootSectorHeader(BootSectorHeader):
60 """FAT32-specific header implementation."""
61
62 #: FAT32 header layout in struct formatted string
63 HEADER_LAYOUT = BootSectorHeader.HEADER_LAYOUT + "LHHLHH12sBBBL11s8s"
64 #: FAT32 header fields when extracted with fat32_header_layout
65 HEADER_VARS = BootSectorHeader.HEADER_VARS + \
66 ["BPB_FATSz32", "BPB_ExtFlags", "BPB_FSVer", "BPB_RootClus",
67 "BPB_FSInfo", "BPB_BkBootSec", "BPB_Reserved", "BS_DrvNum",
68 "BS_Reserved1", "BS_BootSig", "BS_VolID", "BS_VolLab",
69 "BS_FilSysType"]