summaryrefslogtreecommitdiffstats
path: root/src/exfat.h
blob: 54ae4d800a6a41eb158c69163f32e648e3acadec (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*

    file: exfat.h

    Copyright (C) 2010-2011 Christophe GRENIER <grenier@cgsecurity.org>
  
    this software is free software; you can redistribute it and/or modify
    it under the terms of the gnu general public license as published by
    the free software foundation; either version 2 of the license, or
    (at your option) any later version.
  
    this program is distributed in the hope that it will be useful,
    but without any warranty; without even the implied warranty of
    merchantability or fitness for a particular purpose.  see the
    gnu general public license for more details.
  
    You should have received a copy of the GNU General Public License along
    with this program; if not, write the Free Software Foundation, Inc., 51
    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

 */
#ifndef _EXFAT_H
#define _EXFAT_H
#ifdef __cplusplus
extern "C" {
#endif
#define EXFAT_BS_SIZE	512

struct exfat_super_block {
        unsigned char   jmp_boot[3];            /* boot strap short or near jump */
        unsigned char   oem_id[8];              /* oem-id */
        unsigned char   unused0;                /* 0x00... */
        uint32_t  	unused1[13];
	uint64_t  	start_sector;           /* 0x40 start sector of partition */
	uint64_t  	nr_sectors;             /* number of sectors of partition */
	uint32_t  	fat_blocknr;            /* 0x50 start blocknr of FAT */
	uint32_t  	fat_block_counts;       /* number of FAT blocks */
	uint32_t  	clus_blocknr;           /* start blocknr of cluster */
	uint32_t  	total_clusters;         /* number of total clusters */
	uint32_t  	rootdir_clusnr;         /* 0x60 start clusnr of rootdir */
	uint32_t  	serial_number;          /* volume serial number */
	unsigned char   xxxx01;                 /* ??? (0x00 or any value (?)) */
	unsigned char   xxxx02;                 /* ??? (0x01 or 0x00 (?)) */
	uint16_t  	state;                  /* state of this volume */
	unsigned char   blocksize_bits;         /* 0x6c bits of block size */
	unsigned char   block_per_clus_bits;    /* bits of blocks per cluster */
	unsigned char   number_of_fats;
	unsigned char   drive_select;           /* Used by INT 13 */
	unsigned char   allocated_percent;      /* 0x70 percentage of allocated space (?) */
	unsigned char   xxxx05[397];            /* ??? (0x00...) */
	uint16_t  	signature;              /* 0xaa55 */
} __attribute__ ((gcc_struct, __packed__));

struct exfat_file_entry
{
  uint8_t  type;
  uint8_t  sec_count;
  uint16_t checksum;
  uint16_t attr;
  uint16_t reserved1;
  uint16_t ctime;
  uint16_t cdate;
  uint16_t mtime;
  uint16_t mdate;
  uint16_t atime;
  uint16_t adate;
  uint8_t  cms;
  uint8_t  mms;
  uint8_t  ctz;
  uint8_t  mtz;
  uint8_t  reserved2[7];
} __attribute__ ((gcc_struct, __packed__));

struct exfat_stream_ext_entry
{
  uint8_t  type;
  uint8_t  sec_flags;
  uint8_t  reserved1;
  uint8_t  name_length;
  uint16_t name_hash;
  uint16_t reserved2;
  uint64_t valid_data_length;
  uint32_t reserved3;
  uint32_t first_cluster;
  uint64_t data_length;
} __attribute__ ((gcc_struct, __packed__));

struct exfat_alloc_bitmap_entry
{
  uint8_t  type;
  uint8_t  bitmap_flags;
  uint8_t  reserved[18];
  uint32_t first_cluster;
  uint64_t data_length;
} __attribute__ ((gcc_struct, __packed__));

/*@
  @ requires \valid_read(exfat_header);
  @ assigns \nothing;
  @*/
uint64_t exfat_cluster_to_offset(const struct exfat_super_block *exfat_header, const unsigned int cluster);

/*@
  @ requires \valid(disk);
  @ requires valid_disk(disk);
  @ requires \valid_read(partition);
  @ requires \valid_read(exfat_header);
  @ requires \separated(disk, partition, exfat_header, (char *)buffer);
  @ decreases 0;
  @*/
int exfat_read_cluster(disk_t *disk, const partition_t *partition, const struct exfat_super_block*exfat_header, void *buffer, const unsigned int cluster);

/*@
  @ requires \valid(disk);
  @ requires valid_disk(disk);
  @ requires \valid(partition);
  @ requires \separated(disk, partition);
  @ decreases 0;
  @*/
int check_exFAT(disk_t *disk, partition_t *partition);

/*@
  @ requires \valid_read(disk);
  @ requires valid_disk(disk);
  @ requires \valid(partition);
  @ requires valid_partition(partition);
  @ requires \separated(disk, exfat_header, partition);
  @*/
int recover_exFAT(const disk_t *disk, const struct exfat_super_block *exfat_header, partition_t *partition);

/*@
  @ requires \valid_read(exfat_header);
  @ assigns \nothing;
  @*/
int test_exFAT(const struct exfat_super_block *exfat_header);

#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
#endif