forked from espressif/arduino-esp32
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfirmware_msc_fat.h
145 lines (127 loc) · 5.61 KB
/
firmware_msc_fat.h
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
141
142
143
144
145
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FAT_U8(v) ((v) & 0xFF)
#define FAT_U16(v) FAT_U8(v), FAT_U8((v) >> 8)
#define FAT_U32(v) FAT_U8(v), FAT_U8((v) >> 8), FAT_U8((v) >> 16), FAT_U8((v) >> 24)
#define FAT12_TBL2B(l, h) FAT_U8(l), FAT_U8(((l >> 8) & 0xF) | ((h << 4) & 0xF0)), FAT_U8(h >> 4)
#define FAT_MS2B(s, ms) FAT_U8(((((s) & 0x1) * 1000) + (ms)) / 10)
#define FAT_HMS2B(h, m, s) FAT_U8(((s) >> 1) | (((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x7) | ((h) << 3))
#define FAT_YMD2B(y, m, d) FAT_U8(((d) & 0x1F) | (((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x1) | ((((y) - 1980) & 0x7F) << 1))
#define FAT_MS2V(s, ms) FAT_U8(((((s) & 0x1) * 1000) + (ms)) / 10)
#define FAT_HMS2V(h, m, s) (FAT_U8(((s) >> 1) | (((m) & 0x7) << 5)) | (FAT_U8((((m) >> 3) & 0x7) | ((h) << 3)) << 8))
#define FAT_YMD2V(y, m, d) (FAT_U8(((d) & 0x1F) | (((m) & 0x7) << 5)) | (FAT_U8((((m) >> 3) & 0x1) | ((((y) - 1980) & 0x7F) << 1)) << 8))
#define FAT_B2HMS(hms) ((hms >> 11) & 0x1F), ((hms >> 5) & 0x3F), ((hms & 0x1F) << 1)
#define FAT_B2YMD(ymd) (((ymd >> 9) & 0x7F) + 1980), ((ymd >> 5) & 0x0F), (ymd & 0x1F)
#define FAT_FILE_ATTR_READ_ONLY 0x01
#define FAT_FILE_ATTR_HIDDEN 0x02
#define FAT_FILE_ATTR_SYSTEM 0x04
#define FAT_FILE_ATTR_VOLUME_LABEL 0x08
#define FAT_FILE_ATTR_SUBDIRECTORY 0x10
#define FAT_FILE_ATTR_ARCHIVE 0x20
#define FAT_FILE_ATTR_DEVICE 0x40
static const uint16_t DISK_SECTOR_SIZE = 512;
#define FAT_SIZE_TO_SECTORS(bytes) ((bytes) / DISK_SECTOR_SIZE) + (((bytes) % DISK_SECTOR_SIZE) ? 1 : 0)
typedef struct __attribute__((packed)) {
uint8_t jump_instruction[3];
char oem_name[8]; //padded with spaces (0x20)
uint16_t bytes_per_sector; //DISK_SECTOR_SIZE usually 512
uint8_t sectors_per_cluster; //Allowed values are 1, 2, 4, 8, 16, 32, 64, and 128
uint16_t reserved_sectors_count; //At least 1 for this sector, usually 32 for FAT32
uint8_t file_alloc_tables_num; //Almost always 2; RAM disks might use 1
uint16_t max_root_dir_entries; //FAT12 and FAT16
uint16_t fat12_sector_num; //DISK_SECTOR_NUM FAT12 and FAT16
uint8_t media_descriptor;
uint16_t sectors_per_alloc_table; //FAT12 and FAT16
uint16_t sectors_per_track; //A value of 0 may indicate LBA-only access
uint16_t num_heads;
uint32_t hidden_sectors_count;
uint32_t total_sectors_32;
uint8_t physical_drive_number; //0x00 for (first) removable media, 0x80 for (first) fixed disk
uint8_t reserved0;
uint8_t extended_boot_signature; //should be 0x29
uint32_t serial_number; //0x1234 => 1234
char volume_label[11]; //padded with spaces (0x20)
char file_system_type[8]; //padded with spaces (0x20)
uint8_t reserved[448];
uint16_t signature; //should be 0xAA55
} fat_boot_sector_t;
typedef struct __attribute__((packed)) {
union {
struct {
char file_name[8]; //padded with spaces (0x20)
char file_extension[3]; //padded with spaces (0x20)
};
struct {
uint8_t file_magic; // 0xE5:deleted, 0x05:will_be_deleted, 0x00:end_marker, 0x2E:dot_marker(. or ..)
char file_magic_data[10];
};
char volume_label[11]; //padded with spaces (0x20)
};
uint8_t file_attr; //mask of FAT_FILE_ATTR_*
uint8_t reserved; //always 0
uint8_t creation_time_ms; //ms * 10; max 1990 (1s 990ms)
uint16_t creation_time_hms; // [5:6:5] => h:m:(s/2)
uint16_t creation_time_ymd; // [7:4:5] => (y+1980):m:d
uint16_t last_access_ymd;
uint16_t extended_attr;
uint16_t last_modified_hms;
uint16_t last_modified_ymd;
uint16_t data_start_sector;
uint32_t file_size;
} fat_dir_entry_t;
typedef struct __attribute__((packed)) {
union {
struct {
uint8_t number : 5;
uint8_t reserved0 : 1;
uint8_t llfp : 1;
uint8_t reserved1 : 1;
} seq;
uint8_t seq_num; //0xE5: Deleted Entry
};
uint16_t name0[5];
uint8_t attr; //ALWAYS 0x0F
uint8_t type; //ALWAYS 0x00
uint8_t dos_checksum;
uint16_t name1[6];
uint16_t first_cluster; //ALWAYS 0x0000
uint16_t name2[2];
} fat_lfn_entry_t;
typedef union {
fat_dir_entry_t dir;
fat_lfn_entry_t lfn;
} fat_entry_t;
const char *fat_file_system_type(bool fat16);
uint16_t fat_sectors_per_alloc_table(uint32_t sector_num, bool fat16);
uint8_t *fat_add_table(uint8_t *dst, fat_boot_sector_t *boot, bool fat16);
void fat_set_table_index(uint8_t *table, uint16_t index, uint16_t value, bool fat16);
fat_boot_sector_t *fat_add_boot_sector(
uint8_t *dst, uint16_t sector_num, uint16_t table_sectors, const char *file_system_type, const char *volume_label, uint32_t serial_number
);
fat_dir_entry_t *fat_add_label(uint8_t *dst, const char *volume_label);
fat_dir_entry_t *fat_add_root_file(
uint8_t *dst, uint8_t index, const char *file_name, const char *file_extension, size_t file_size, uint16_t data_start_sector, bool is_fat16
);
uint8_t fat_lfn_checksum(const uint8_t *short_filename);
#ifdef __cplusplus
}
#endif