1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** FileX Component                                                       */
16 /**                                                                       */
17 /**   Fault Tolerant                                                      */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /**************************************************************************/
24 /*                                                                        */
25 /*  COMPONENT DEFINITION                                   RELEASE        */
26 /*                                                                        */
27 /*    fx_fault_tolerant.h                                 PORTABLE C      */
28 /*                                                           6.1          */
29 /*  AUTHOR                                                                */
30 /*                                                                        */
31 /*    William E. Lamie, Microsoft Corporation                             */
32 /*                                                                        */
33 /*  DESCRIPTION                                                           */
34 /*                                                                        */
35 /*    This file defines the FileX Fault Tolerant component constants,     */
36 /*    data definitions, and external references.  It is assumed that      */
37 /*    fx_api.h (and fx_port.h) have already been included.                */
38 /*                                                                        */
39 /*  RELEASE HISTORY                                                       */
40 /*                                                                        */
41 /*    DATE              NAME                      DESCRIPTION             */
42 /*                                                                        */
43 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
44 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
45 /*                                            resulting in version 6.1    */
46 /*                                                                        */
47 /**************************************************************************/
48 
49 #ifndef _FX_FAULT_TOLERANT_H_
50 #define _FX_FAULT_TOLERANT_H_
51 
52 #ifdef FX_ENABLE_FAULT_TOLERANT
53 
54 #ifndef FX_FAULT_TOLERANT
55 #error "FX_FAULT_TOLERANT must be defined with FX_ENABLE_FAULT_TOLERANT"
56 #endif /* FX_FAULT_TOLERANT */
57 
58 /* Define ID of fault tolerant. */
59 #define FX_FAULT_TOLERANT_ID                      0x46544C52
60 
61 /* Define fault tolerant version. */
62 #define FX_FAULT_TOLERANT_VERSION_MAJOR           0x01
63 #define FX_FAULT_TOLERANT_VERSION_MINOR           0x00
64 
65 /* Define byte offset in boot sector where the cluster number of the Fault Tolerant Log file is.
66    Note that this field (byte 116 to 119) is marked as reserved by FAT 12/16/32 specification. */
67 #ifndef FX_FAULT_TOLERANT_BOOT_INDEX
68 #define FX_FAULT_TOLERANT_BOOT_INDEX              116
69 #endif /* FX_FAULT_TOLERANT_BOOT_INDEX */
70 
71 /* Define the extension invoked when fault tolerant log is recovered or applied during enable API. */
72 #ifndef FX_FAULT_TOLERANT_ENABLE_EXTENSION
73 #define FX_FAULT_TOLERANT_ENABLE_EXTENSION
74 #endif /* FX_FAULT_TOLERANT_ENABLE_EXTENSION */
75 
76 /* Define the extension invoked when fault tolerant log is applied. */
77 #ifndef FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
78 #define FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
79 #endif /* FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION */
80 
81 /* If not-defined, default port-specific processing extensions to white space.  */
82 #ifndef FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION
83 #define FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION
84 #endif /* FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION */
85 
86 /* Define the maximum size of log file. */
87 #define FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE   3072
88 
89 /* For backward compatibility, map the symbols deprecated to FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE. */
90 #ifndef FX_FAULT_TOLERANT_MINIMAL_CLUSTER
91 #define FX_FAULT_TOLERANT_MINIMAL_CLUSTER         FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE
92 #endif /* FX_FAULT_TOLERANT_MINIMAL_CLUSTER */
93 #ifndef FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE
94 #define FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE     FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE
95 #endif /* FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE */
96 
97 /* Define the states of the fault tolerant module. */
98 #define FX_FAULT_TOLERANT_STATE_IDLE              0x00u
99 #define FX_FAULT_TOLERANT_STATE_STARTED           0x01u
100 #define FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN     0x02u
101 
102 /* Define types of logs. */
103 #define FX_FAULT_TOLERANT_FAT_LOG_TYPE            1
104 #define FX_FAULT_TOLERANT_DIR_LOG_TYPE            2
105 #define FX_FAULT_TOLERANT_BITMAP_LOG_TYPE         3
106 
107 /* Define operations of FAT chain. */
108 #define FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER       0     /* Recover new FAT chain. */
109 #define FX_FAULT_TOLERANT_FAT_CHAIN_CLEANUP       1     /* Cleanup old FAT chain. */
110 
111 /* Define flags for FAT chain log. */
112 #define FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID    0x01
113 #define FX_FAULT_TOLERANT_FLAG_BITMAP_USED        0x02
114 
115 /* Define size of each section in log file. */
116 #define FX_FAULT_TOLERANT_LOG_HEADER_SIZE         sizeof(FX_FAULT_TOLERANT_LOG_HEADER)
117 #define FX_FAULT_TOLERANT_FAT_CHAIN_SIZE          sizeof(FX_FAULT_TOLERANT_FAT_CHAIN)
118 #define FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE sizeof(FX_FAULT_TOLERANT_LOG_CONTENT)
119 
120 /* Define offset of each section in log file. */
121 #define FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET        (FX_FAULT_TOLERANT_LOG_HEADER_SIZE)
122 #define FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET      (FX_FAULT_TOLERANT_LOG_HEADER_SIZE + FX_FAULT_TOLERANT_FAT_CHAIN_SIZE)
123 
124 /* Define size of log entries. */
125 /* The total size of DIR log entry is variable. 16 is the fixed size of DIR log entry. */
126 #define FX_FAULT_TOLERANT_FAT_LOG_ENTRY_SIZE      sizeof(FX_FAULT_TOLERANT_FAT_LOG)
127 #define FX_FAULT_TOLERANT_BITMAP_LOG_ENTRY_SIZE   sizeof(FX_FAULT_TOLERANT_BITMAP_LOG)
128 #define FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE      sizeof(FX_FAULT_TOLERANT_DIR_LOG)
129 
130 #ifdef FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION
131 #define FX_FAULT_TOLERANT_TRANSACTION_FAIL _fx_fault_tolerant_transaction_fail
132 #else
133 /* Define transaction fail for fault tolerant. */
134 #define FX_FAULT_TOLERANT_TRANSACTION_FAIL(m)                            \
135     if ((m) -> fx_media_fault_tolerant_enabled == FX_TRUE)               \
136     {                                                                    \
137         (m) -> fx_media_fault_tolerant_transaction_count--;              \
138         if ((m) -> fx_media_fault_tolerant_transaction_count == 0)       \
139         {                                                                \
140             _fx_fault_tolerant_recover(m);                               \
141             _fx_fault_tolerant_reset_log_file(m);                        \
142         }                                                                \
143     }
144 
145 #endif /* FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION */
146 
147 /* Log file format
148  * The entire log file fits into one cluster.
149  *
150  *                      1                   2                   3
151  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
152  * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
153  * +                                ID                             +
154  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
155  * +   Total Log Size (in Bytes)    +        Header Checksum       +      Log Header
156  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
157  * +  version major + version minor +           reserved           +
158  * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
159  * +      Checksum of FAT chain     +     Flag      |   Reserved   +
160  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
161  * +                   Insertion Point - Front                     +
162  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
163  * +            Head cluster of newly created FAT chain            +
164  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      FAT Chain
165  * +                 Head cluster of original FAT chain            +
166  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
167  * +                   Insertion Point - Back                      +
168  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
169  * +                     Next Deletion Point                       +
170  * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
171  * +     checksum of log content    +      count of log entries    +
172  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
173  * + (log 0)                        .                              +
174  * +                                .                              +
175  * +                                .                              +
176  * +                                .                              +
177  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
178  * + (log 1)                        .                              +
179  * +                                .                              +      Log Entries
180  * +                                .                              +
181  * +                                .                              +
182  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
183  * +                               ...                             +
184  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
185  * + (log N)                        .                              +
186  * +                                .                              +
187  * +                                .                              +
188  * +                                .                              +
189  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
190  *
191  *
192  * Log Header
193  *
194  *  * ID: It is fixed value FX_FAULT_TOLERANT_ID.
195  *  * Total Size: Total size (in bytes) of the log file, including Log Header, FAT Chain and Log Entries
196  *  * Header Checksum: It is the checksum of all data in log header.
197  *  * Version Major: The major version number.
198  *  * Version Minor: The minor version number.
199  *  * Reserved: Reserved for future use.
200  *
201  *  FAT Chain
202  *
203  *  * Checksum of FAT chain: It is the checksum of all data in the FAT Chain section.
204  *  * Flag: 8 bits. The 1-6 bits are not used (from left to right).
205  *      bit 7: When set, bitmap is used in old FAT chain.
206  *      bit 8: When set, FAT chain is valid.
207  *  * Reserved: Reserved for future use.
208  *  * Insertion Point - Front:  The cluster where the newly created chain is attached to
209  *  * Head cluster of new FAT chain. It is the head cluster of new FAT chain.
210  *  * Head cluster of oritinal FAT chain. It is the head cluster of the original FAT chain,
211  *        which will be removed.
212  *  * Inswertion Point - Back:  The original cluster right after the newly created chain is inserted.
213  *  * Next Deletion Point: next session of cluster to delete. It is used during deleting FAT chain.
214  *      The deltion is carried out in stages for perofmrance reasons.  When delting a FAT chain, the
215  *      Next Deletion Point is chosen, and the chain between head and the Next Deletion Point is deleted.
216  *
217  *  Log Entries:
218  *
219  *  * Checksum of log entries: It is the checksum of all data in Log Entries
220  *  * Counter of log entries: It is the counter of all log entries in Log content.
221  *  * log 0 ... log N: Log entries. The formats are described below.
222  */
223 
224 /* Defined structure of log header.
225 
226 
227  */
228 typedef struct FX_FAULT_TOLERANT_LOG_HEADER_STRUCT
229 {
230     ULONG  fx_fault_tolerant_log_header_id;
231     USHORT fx_fault_tolerant_log_header_total_size;
232     USHORT fx_fault_tolerant_log_header_checksum;
233     UCHAR  fx_fault_tolerant_log_header_version_major;
234     UCHAR  fx_fault_tolerant_log_header_version_minor;
235     USHORT fx_fault_tolerant_log_header_reserved;
236 } FX_FAULT_TOLERANT_LOG_HEADER;
237 
238 /* Define structure of FAT chain. */
239 typedef struct FX_FAULT_TOLERANT_FAT_CHAIN_STRUCT
240 {
241     USHORT fx_fault_tolerant_FAT_chain_checksumm;
242     UCHAR  fx_fault_tolerant_FAT_chain_flag;
243     UCHAR  fx_fault_tolerant_FAT_chain_reserved;
244 
245     ULONG  fx_fault_tolerant_FAT_chain_insertion_front;
246     ULONG  fx_fault_tolerant_FAT_chain_head_new;
247     ULONG  fx_fault_tolerant_FAT_chain_head_original;
248     ULONG  fx_fault_tolerant_FAT_chain_insertion_back;
249     ULONG  fx_fault_tolerant_FAT_chain_next_deletion;
250 } FX_FAULT_TOLERANT_FAT_CHAIN;
251 
252 
253 /* Define structure of Log content. */
254 typedef struct FX_FAULT_TOLERANT_LOG_CONTENT_STRUCT
255 {
256     USHORT fx_fault_tolerant_log_content_checksum;
257     USHORT fx_fault_tolerant_log_content_count;
258 } FX_FAULT_TOLERANT_LOG_CONTENT;
259 
260 
261 /* 3 types of log entries are defined. */
262 /* FAT log format
263  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
264  * +              type              +           size               +
265  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
266  * +                             cluster                           +
267  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
268  * +                              value                            +
269  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
270  *
271  * Description:
272  *
273  * Type:     FX_FAULT_TOLERANT_FAT_LOG.
274  * Size:     The size of this log entry.
275  * Cluster:  The cluster number in FAT.
276  * Value:    The value of cluster in FAT.
277  *
278  */
279 typedef struct FX_FAULT_TOLERANT_FAT_LOG_STRUCT
280 {
281     USHORT fx_fault_tolerant_FAT_log_type;
282     USHORT fx_fault_tolerant_FAT_log_size;
283     ULONG  fx_fault_tolerant_FAT_log_cluster;
284     ULONG  fx_fault_tolerant_FAT_log_value;
285 } FX_FAULT_TOLERANT_FAT_LOG;
286 
287 /* DIR log format
288  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
289  * +              type              +           size               +
290  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
291  * +                         sector offset                         +
292  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
293  * +                           log sector                          +
294  * +                                                               +
295  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
296  * +                           log data                            +
297  * +                              .                                +
298  * +                              .                                +
299  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
300  *
301  * Fields description,
302  *
303  * Type:          FX_FAULT_TOLERANT_DIRECTORY_LOG
304  * Size:          The size of this log entry.
305  * Sector Offset: The offset in original sector this DIR is trying to write to.
306  * Log Sector:    The original sector this DIR is trying to write to.
307  * Log Data:      Content of DIR entries.
308  *
309  */
310 typedef struct FX_FAULT_TOLERANT_DIR_LOG_STRUCT
311 {
312     USHORT  fx_fault_tolerant_dir_log_type;
313     USHORT  fx_fault_tolerant_dir_log_size;
314     ULONG   fx_fault_tolerant_dir_log_offset;
315     ULONG64 fx_fault_tolerant_dir_log_sector;
316 } FX_FAULT_TOLERANT_DIR_LOG;
317 
318 /* Bitmap log format
319  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
320  * +              type              +           size               +
321  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
322  * +                             cluster                           +
323  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
324  * +                              value                            +
325  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
326  *
327  * Description,
328  *
329  * Type:     FX_FAULT_TOLERANT_BITMAP_LOG.
330  * Size:     The size of this log entry.
331  * Cluster:  The cluster number in FAT.
332  * Value:    The value of cluster in FAT.
333  */
334 typedef struct FX_FAULT_TOLERANT_BITMAP_LOG_STRUCT
335 {
336     USHORT fx_fault_tolerant_bitmap_log_type;
337     USHORT fx_fault_tolerant_bitmap_log_size;
338     ULONG  fx_fault_tolerant_bitmap_log_cluster;
339     ULONG  fx_fault_tolerant_bitmap_log_value;
340 } FX_FAULT_TOLERANT_BITMAP_LOG;
341 
342 
343 /* This function checks whether or not the log file exists, and creates the log file if it does not exist. */
344 UINT _fx_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size);
345 UINT _fxe_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size);
346 
347 /* This function resets statistics and marks the start of a transaction. */
348 UINT _fx_fault_tolerant_transaction_start(FX_MEDIA *media_ptr);
349 
350 /* This function marks the end of a transaction and completes the log file.
351  * Then it applies all data in the log file to the file system.
352  * Finally it resets the log header section. */
353 UINT _fx_fault_tolerant_transaction_end(FX_MEDIA *media_ptr);
354 
355 /* This function resets the log file. */
356 UINT _fx_fault_tolerant_reset_log_file(FX_MEDIA *media_ptr);
357 
358 /* This function applies the log file to the file system. */
359 UINT _fx_fault_tolerant_apply_logs(FX_MEDIA *media_ptr);
360 
361 /* This function recovers FAT chain. */
362 UINT _fx_fault_tolerant_recover(FX_MEDIA *media_ptr);
363 
364 /* This function adds a FAT log entry. */
365 UINT _fx_fault_tolerant_add_FAT_log(FX_MEDIA *media_ptr, ULONG cluster, ULONG value);
366 
367 /* This function adds a directory log entry. */
368 UINT _fx_fault_tolerant_add_dir_log(FX_MEDIA *media_ptr, ULONG64 logical_sector, ULONG offset,
369                                     UCHAR *data, ULONG data_size);
370 
371 /* This function sets the FAT chain. */
372 UINT _fx_fault_tolerant_set_FAT_chain(FX_MEDIA *media_ptr, UINT use_bitmap, ULONG insertion_front,
373                                       ULONG new_head_cluster, ULONG original_head_cluster, ULONG insertion_back);
374 
375 /* This function reads a FAT entry from log file. If it doesn't exist in log file, return and read from FAT entry directly. */
376 UINT _fx_fault_tolerant_read_FAT(FX_MEDIA *media_ptr, ULONG cluster, ULONG *value, ULONG log_type);
377 
378 /* This function reads directory sector from log file. */
379 UINT _fx_fault_tolerant_read_directory_sector(FX_MEDIA *media_ptr, ULONG64 logical_sector,
380                                               VOID *buffer_ptr, ULONG64 sectors);
381 
382 /* This function calculates the checksum of the log header. */
383 USHORT _fx_fault_tolerant_calculate_checksum(UCHAR *data, UINT len);
384 
385 /* This function cleans up FAT chain. */
386 UINT _fx_fault_tolerant_cleanup_FAT_chain(FX_MEDIA *media_ptr, UINT operation);
387 
388 /* This function reads log file from file system to memory buffer. */
389 UINT _fx_fault_tolerant_read_log_file(FX_MEDIA *media_ptr);
390 
391 /* This function writes data of one sector from memory to log file in file system. */
392 UINT _fx_fault_tolerant_write_log_file(FX_MEDIA *media_ptr, ULONG relative_sector);
393 
394 /* This function creates log file. */
395 UINT _fx_fault_tolerant_create_log_file(FX_MEDIA *media_ptr);
396 
397 #ifdef FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION
398 /* This function cleans up resources created by fault tolerant when transaction fails. */
399 UINT _fx_fault_tolerant_transaction_fail(FX_MEDIA *media_ptr);
400 #endif /* FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION */
401 
402 
403 #endif /* FX_ENABLE_FAULT_TOLERANT */
404 
405 #endif /* _FX_FAULT_TOLERANT_H_ */
406 
407