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 #define FX_SOURCE_CODE
23
24 #include "fx_api.h"
25 #include "fx_utility.h"
26 #include "fx_fault_tolerant.h"
27
28
29 #ifdef FX_ENABLE_FAULT_TOLERANT
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _fx_fault_tolerant_apply_logs PORTABLE C */
35 /* 6.2.0 */
36 /* AUTHOR */
37 /* */
38 /* William E. Lamie, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* This function applies changes to the file system. The changes are */
43 /* already recorded in the fault tolerant log file. Therefore this */
44 /* function reads the content of the log entries and apply these */
45 /* changes to the file system. */
46 /* */
47 /* INPUT */
48 /* */
49 /* media_ptr Media control block pointer */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* return status */
54 /* */
55 /* CALLS */
56 /* */
57 /* _fx_utility_logical_sector_write Write a logical sector */
58 /* _fx_utility_logical_sector_read Read a logical sector */
59 /* _fx_utility_16_unsigned_read Read a USHORT from memory */
60 /* _fx_utility_32_unsigned_read Read a ULONG from memory */
61 /* _fx_utility_64_unsigned_read Read a ULONG64 from memory */
62 /* _fx_utility_FAT_entry_write Write a FAT entry */
63 /* _fx_fault_tolerant_cleanup_FAT_chain Cleanup FAT chain */
64 /* memcpy Memory Copy */
65 /* _fx_utility_FAT_flush Flush written FAT entries */
66 /* _fx_utility_logical_sector_flush Flush written logical sectors */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* _fx_fault_tolerant_enable */
71 /* _fx_fault_tolerant_transaction_end */
72 /* */
73 /* RELEASE HISTORY */
74 /* */
75 /* DATE NAME DESCRIPTION */
76 /* */
77 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
78 /* 09-30-2020 William E. Lamie Modified comment(s), verified */
79 /* memcpy usage, */
80 /* resulting in version 6.1 */
81 /* 10-31-2022 Tiejun Zhou Modified comment(s), fixed */
82 /* overflow in log size check, */
83 /* resulting in version 6.2.0 */
84 /* */
85 /**************************************************************************/
_fx_fault_tolerant_apply_logs(FX_MEDIA * media_ptr)86 UINT _fx_fault_tolerant_apply_logs(FX_MEDIA *media_ptr)
87 {
88 UINT status;
89 ULONG64 log_sector;
90 ULONG remaining_logs;
91 ULONG copy_size;
92 ULONG copy_offset;
93 UCHAR *current_ptr;
94 ULONG size;
95 USHORT log_type;
96 ULONG log_len;
97 FX_FAULT_TOLERANT_LOG_HEADER *log_header;
98 FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
99 FX_FAULT_TOLERANT_LOG_CONTENT *log_content;
100 FX_FAULT_TOLERANT_FAT_LOG *fat_log;
101 FX_FAULT_TOLERANT_DIR_LOG *dir_log;
102
103 /* Set log header, FAT chain and log content pointer. */
104 log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
105 FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
106 log_content = (FX_FAULT_TOLERANT_LOG_CONTENT *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
107 FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET);
108
109 /* Find the size of the log file. */
110 size = _fx_utility_16_unsigned_read((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size);
111
112 /* Extended port-specific processing macro, which is by default defined to white space. */
113 FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
114
115 size -= FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
116
117 /* Find the number of log entries. */
118 remaining_logs = _fx_utility_16_unsigned_read((UCHAR *)&log_content -> fx_fault_tolerant_log_content_count);
119
120 /* Get start address of logs. */
121 current_ptr = (UCHAR *)log_content + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
122
123 /* Loop through all the logs to apply the changes. */
124 while (remaining_logs)
125 {
126
127 /* Obtain log type of this entry. */
128 log_type = (USHORT)_fx_utility_16_unsigned_read(current_ptr);
129
130 /* Read log length. */
131 log_len = _fx_utility_16_unsigned_read(current_ptr + 2);
132
133
134 /* Validate log entry size. */
135 if (log_len > size)
136 {
137
138 /* Something wrong with log file. */
139 return(FX_FILE_CORRUPT);
140 }
141
142 /* Reduce the total log file size. */
143 size -= log_len;
144
145 /* Process log entry by type. */
146 switch (log_type)
147 {
148 case FX_FAULT_TOLERANT_FAT_LOG_TYPE:
149
150 /* This is a FAT log. */
151 fat_log = (FX_FAULT_TOLERANT_FAT_LOG *)current_ptr;
152
153 /* Write FAT entry. */
154 status = _fx_utility_FAT_entry_write(media_ptr,
155 _fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_cluster),
156 _fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_value));
157
158 if (status != FX_SUCCESS)
159 {
160
161 /* Return the error status. */
162 return(status);
163 }
164 break;
165
166 case FX_FAULT_TOLERANT_DIR_LOG_TYPE:
167
168 /* This is a DIR log. */
169 dir_log = (FX_FAULT_TOLERANT_DIR_LOG *)current_ptr;
170
171 log_sector = _fx_utility_64_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_sector);
172
173 /* Get the destination sector. */
174 status = _fx_utility_logical_sector_read(media_ptr,
175 log_sector,
176 media_ptr -> fx_media_memory_buffer,
177 ((ULONG) 1), FX_DATA_SECTOR);
178
179 if (status != FX_SUCCESS)
180 {
181
182 /* Return the error status. */
183 return(status);
184 }
185
186 /* Set copy information. */
187 copy_offset = _fx_utility_32_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_offset);
188
189
190 copy_size = log_len - FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE;
191
192 if (((ULONG64)copy_offset + (ULONG64)copy_size) > (ULONG64)(media_ptr -> fx_media_memory_size))
193 {
194 return(FX_FILE_CORRUPT);
195 }
196
197 /* Copy data into destination sector. */
198 memcpy(media_ptr -> fx_media_memory_buffer + copy_offset, /* Use case of memcpy is verified. */
199 current_ptr + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE, copy_size);
200
201
202 /* Write back the current logical sector. */
203 status = _fx_utility_logical_sector_write(media_ptr,
204 log_sector,
205 media_ptr -> fx_media_memory_buffer,
206 ((ULONG) 1), FX_DIRECTORY_SECTOR);
207
208 if (status != FX_SUCCESS)
209 {
210
211 /* Return the error status. */
212 return(status);
213 }
214 break;
215
216 default:
217
218 /* Wrong type. */
219 return(FX_SECTOR_INVALID);
220 }
221
222 /* Decrement the remaining log counter. */
223 remaining_logs--;
224
225 /* Move to start position of next log entry. */
226 current_ptr += log_len;
227 }
228
229 /* Check whether or not to process FAT chain. */
230 if (FAT_chain -> fx_fault_tolerant_FAT_chain_flag & FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID)
231 {
232
233 /* Free old link of FAT. */
234 status = _fx_fault_tolerant_cleanup_FAT_chain(media_ptr, FX_FAULT_TOLERANT_FAT_CHAIN_CLEANUP);
235 if (status != FX_SUCCESS)
236 {
237
238 /* Return the error status. */
239 return(status);
240 }
241 }
242
243 /* Flush the internal logical sector cache. */
244 status = _fx_utility_logical_sector_flush(media_ptr, 1, (ULONG64) media_ptr -> fx_media_total_sectors, FX_FALSE);
245
246 /* Check for a bad status. */
247 if (status != FX_SUCCESS)
248 {
249
250 /* Return the bad status. */
251 return(status);
252 }
253
254 /* Flush FAT table. */
255 #ifdef FX_FAULT_TOLERANT
256
257 /* Ensure the new FAT chain is properly written to the media. */
258
259 /* Flush the cached individual FAT entries */
260 _fx_utility_FAT_flush(media_ptr);
261 #endif
262
263 /* Return success. */
264 return(FX_SUCCESS);
265 }
266 #endif /* FX_ENABLE_FAULT_TOLERANT */
267
268