1 #ifndef FX_STANDALONE_ENABLE
2 #include   "tx_api.h"
3 #include   "tx_thread.h"
4 #include   "tx_timer.h"
5 #endif
6 #include   "fx_api.h"
7 #include   "fx_unicode.h"
8 #include   "fx_utility.h"
9 #include   "fx_fault_tolerant.h"
10 #include   <stdio.h>
11 #include   <string.h>
12 #include   "fx_ram_driver_test.h"
13 extern void    test_control_return(UINT status);
14 void    filex_fault_tolerant_enable_2_test_application_define(void *first_unused_memory);
15 
16 #if defined (FX_ENABLE_FAULT_TOLERANT) && defined (FX_FAULT_TOLERANT)
17 
18 #define DEMO_STACK_SIZE         4096
19 #define CACHE_SIZE              2048
20 #define FAULT_TOLERANT_SIZE     FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE
21 
22 
23 /* Define the ThreadX and FileX object control blocks...  */
24 
25 #ifndef FX_STANDALONE_ENABLE
26 static TX_THREAD                ftest_0;
27 #endif
28 static FX_MEDIA                 ram_disk;
29 static UCHAR                    *pointer;
30 
31 /* Define the counters used in the test application...  */
32 
33 #ifndef FX_STANDALONE_ENABLE
34 static UCHAR                    *cache_buffer;
35 static UCHAR                    *fault_tolerant_buffer;
36 #else
37 static UCHAR                    cache_buffer[CACHE_SIZE];
38 static UCHAR                    fault_tolerant_buffer[FAULT_TOLERANT_SIZE];
39 #endif
40 static CHAR                     read_buffer[10240];
41 
42 #define TEST_COUNT              3
43 
44 /* Define thread prototypes.  */
45 
46 static void    ftest_0_entry(ULONG thread_input);
47 extern void    _fx_ram_driver(FX_MEDIA *media_ptr);
48 extern void    test_control_return(UINT status);
49 
50 
51 /* Define what the initial system looks like.  */
52 
53 #ifdef CTEST
test_application_define(void * first_unused_memory)54 void test_application_define(void *first_unused_memory)
55 #else
56 void    filex_fault_tolerant_enable_2_test_application_define(void *first_unused_memory)
57 #endif
58 {
59 
60 
61 #ifndef FX_STANDALONE_ENABLE
62     /* Setup the working pointer.  */
63     pointer =  (UCHAR *) first_unused_memory;
64 
65     /* Create the main thread.  */
66 
67     tx_thread_create(&ftest_0, "thread 0", ftest_0_entry, 0,
68             pointer, DEMO_STACK_SIZE,
69             4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
70 
71     pointer =  pointer + DEMO_STACK_SIZE;
72 
73     /* Setup memory for the RAM disk and the sector cache.  */
74     cache_buffer =  pointer;
75     pointer += CACHE_SIZE;
76     fault_tolerant_buffer = pointer;
77     pointer += FAULT_TOLERANT_SIZE;
78 #endif
79 
80     /* Initialize the FileX system.  */
81     fx_system_initialize();
82 #ifdef FX_STANDALONE_ENABLE
83     ftest_0_entry(0);
84 #endif
85 }
86 
87 
88 /* Define the test threads.  */
89 
ftest_0_entry(ULONG thread_input)90 static void    ftest_0_entry(ULONG thread_input)
91 {
92 
93 FX_DIR_ENTRY dir_entry1, dir_entry2;
94 ULONG       uentry;
95 ULONG       unicode_size;
96 UINT        status, length;
97 ULONG       actual;
98 UCHAR       buffer[2048];
99 CHAR        destination_name[100];
100 UCHAR       unicode_name_A[] = { 'A', 0, 0, 0};
101 UCHAR       unicode_name_1[] = { 1, 0, 0, 0};
102 UCHAR       unicode_name_2[] = { 1, 0, 1, 0, 0, 0};
103 UCHAR       unicode_name_A1[] = { 'A', 0, 1, 0, 0, 0};
104 UCHAR       *source_buffer;
105 USHORT      log_length;
106 FX_FILE     my_file;
107 ULONG       clusters;
108 ULONG       bytes_per_cluster;
109 ULONG       cluster;
110 FX_LOCAL_PATH local_path;
111 FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
112 
113     FX_PARAMETER_NOT_USED(thread_input);
114 
115     /* Print out some test information banners.  */
116     printf("FileX Test:   Fault Tolerant Enable 2 Test...........................");
117 
118     /* Format the media with FAT16.  This needs to be done before opening it!  */
119     status =  fx_media_format(&ram_disk,
120                              _fx_ram_driver,         // Driver entry
121                              ram_disk_memory_large,  // RAM disk memory pointer
122                              cache_buffer,           // Media buffer pointer
123                              CACHE_SIZE,             // Media buffer size
124                              "MY_RAM_DISK",          // Volume Name
125                              1,                      // Number of FATs
126                              32,                     // Directory Entries
127                              0,                      // Hidden sectors
128                              4200 * 8,               // Total sectors
129                              256,                    // Sector size
130                              8,                      // Sectors per cluster
131                              1,                      // Heads
132                              1);                     // Sectors per track
133     status +=  fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory_large, cache_buffer, CACHE_SIZE);
134     return_if_fail( status == FX_SUCCESS);
135 
136     /* Enable fault tolerant. */
137     status = fx_fault_tolerant_enable( &ram_disk, fault_tolerant_buffer, FAULT_TOLERANT_SIZE);
138     return_if_fail( status == FX_SUCCESS);
139 
140     status = fx_file_create( &ram_disk, "TEST.TXT");
141     status += fx_file_open( &ram_disk, &my_file, "TEST.TXT", FX_OPEN_FOR_WRITE);
142     status += fx_file_allocate( &my_file, 2048);
143     return_if_fail( status == FX_SUCCESS);
144 
145     /* Set the state of fault tolerant as FX_FAULT_TOLERANT_STATE_STARTED and add an extra transaction record. */
146     ram_disk.fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_STARTED;
147     ram_disk.fx_media_fault_tolerant_transaction_count = 1;
148 
149     /* Overflow the size of log file. */
150     source_buffer = fault_tolerant_buffer + FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
151     log_length = (USHORT)_fx_utility_16_unsigned_read( source_buffer + 2);
152     _fx_utility_16_unsigned_write( source_buffer + 2, 0xffff);
153     status = fx_file_truncate_release( &my_file, 26);
154     return_if_fail( status == FX_FILE_CORRUPT);
155 
156     /* Reset the log file to revert our modification and close transaction. */
157     _fx_fault_tolerant_reset_log_file( &ram_disk);
158     status = fx_file_truncate_release( &my_file, 26);
159     return_if_fail( status == FX_SUCCESS);
160 
161     /* Deal with the tail. */
162     status = fx_file_close( &my_file);
163     status += fx_media_close( &ram_disk);
164     return_if_fail( status == FX_SUCCESS);
165 
166     /* Format the media with FAT16.  This needs to be done before opening it!  */
167     status =  fx_media_format(&ram_disk,
168                              _fx_ram_driver,         // Driver entry
169                              ram_disk_memory_large,  // RAM disk memory pointer
170                              cache_buffer,           // Media buffer pointer
171                              CACHE_SIZE,             // Media buffer size
172                              "MY_RAM_DISK",          // Volume Name
173                              1,                      // Number of FATs
174                              32,                     // Directory Entries
175                              0,                      // Hidden sectors
176                              4200 * 8,               // Total sectors
177                              256,                    // Sector size
178                              8,                      // Sectors per cluster
179                              1,                      // Heads
180                              1);                     // Sectors per track
181     status +=  fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory_large, cache_buffer, CACHE_SIZE);
182     return_if_fail( status == FX_SUCCESS);
183 
184     /* Enable fault tolerant. */
185     status = fx_fault_tolerant_enable( &ram_disk, fault_tolerant_buffer, FAULT_TOLERANT_SIZE);
186     return_if_fail( status == FX_SUCCESS);
187 
188     length = fx_unicode_length_get( unicode_name_A);
189     status = fx_unicode_directory_create( &ram_disk, unicode_name_A, length, destination_name);
190 #ifndef FX_STANDALONE_ENABLE
191     status += fx_directory_local_path_set( &ram_disk, &local_path, destination_name);
192 #else
193     status +=  fx_directory_default_set(&ram_disk, destination_name);
194 #endif
195     return_if_fail( status == FX_SUCCESS);
196 
197     /* Create a lot of directries which makes the first level subdir occupy space more than a single cluster, which will leave fat logs in log file. */
198 
199     /* For our special implement of fx_unicode_xx_create, we can only 26 files/directories with the same length of unicode name. */
200     for ( UINT i = 0; i < 26; i++)
201     {
202         length = fx_unicode_length_get( unicode_name_1);
203         status = fx_unicode_directory_create( &ram_disk, unicode_name_1, length, destination_name);
204         return_if_fail( status == FX_SUCCESS);
205         unicode_name_1[0]++;
206     }
207 
208     /* When more directories is attempted to be created, fat logs will be read in fx_directory_search and fx_directory_free_search. */
209     for ( UINT i = 0; i < 6; i++)
210     {
211         length = fx_unicode_length_get( unicode_name_2);
212         status = fx_unicode_directory_create( &ram_disk, unicode_name_2, length, destination_name);
213         return_if_fail( status == FX_SUCCESS);
214         unicode_name_2[0]++;
215     }
216 
217     /* Make an I/O error while _fx_fault_tolerant_apply_log is calling _fx_utility_FAT_entry_write. */
218     _fx_utility_fat_entry_write_error_request = 1;
219     status = fx_unicode_directory_create( &ram_disk, unicode_name_2, length, destination_name);
220     return_if_fail( status == FX_IO_ERROR);
221 
222     /* Make an I/O error while _fx_fault_tolerant_apply_log is calling _fx_utility_logical_sector_read. */
223     _fx_utility_logical_sector_read_error_request = 339;
224     status = fx_unicode_directory_create( &ram_disk, unicode_name_2, length, destination_name);
225     return_if_fail( status == FX_IO_ERROR);
226 
227     /* Make an I/O error while _fx_fault_tolerant_apply_log is calling _fx_utility_logical_sector_write. */
228     _fx_utility_logical_sector_write_error_request = 4;
229     status = fx_unicode_directory_create( &ram_disk, unicode_name_2, length, destination_name);
230     return_if_fail( status == FX_IO_ERROR);
231 
232 #ifndef FX_DISABLE_CACHE
233     /* Make an I/O error while _fx_fault_tolerant_apply_log is calling _fx_utility_logical_sector_flush. */
234     _fx_utility_logical_sector_flush_error_request = 6;
235     status = fx_unicode_directory_create( &ram_disk, unicode_name_2, length, destination_name);
236     return_if_fail( status == FX_IO_ERROR);
237 #endif
238 
239     /* Start transaction manually. */
240     ram_disk.fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_STARTED;
241     ram_disk.fx_media_fault_tolerant_transaction_count = 1;
242     source_buffer = fault_tolerant_buffer + FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
243 
244     /* Modify the length of the log to overflow the size of log file, which will be caught by _fx_fault_tolerant_apply_logs. */
245     log_length = (USHORT)_fx_utility_16_unsigned_read( source_buffer + 2);
246     _fx_utility_16_unsigned_write( source_buffer + 2, 0xffff);
247     status = _fx_fault_tolerant_transaction_end( &ram_disk);
248     return_if_fail( status == FX_FILE_CORRUPT);
249 
250     /* Recover log length. */
251     _fx_utility_16_unsigned_write( source_buffer + 2, log_length);
252 
253     /* Start transaction manually. */
254     ram_disk.fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_STARTED;
255     ram_disk.fx_media_fault_tolerant_transaction_count = 1;
256     source_buffer = fault_tolerant_buffer + FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
257 
258     /* Modify the type of the log as an undefined number, which will be caught by _fx_fault_tolerant_apply_logs. */
259     _fx_utility_16_unsigned_write( source_buffer, 0xffff);
260     status = _fx_fault_tolerant_transaction_end( &ram_disk);
261     return_if_fail( status == FX_SECTOR_INVALID);
262 
263     /* The size of a dir log is larger than a sector which is invalid, which will be caught by _fx_fault_tolerant_apply_logs. */
264     _fx_utility_16_unsigned_write( ram_disk.fx_media_fault_tolerant_memory_buffer + 4, 0xffff);
265     source_buffer = ram_disk.fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
266     _fx_utility_16_unsigned_write( source_buffer, FX_FAULT_TOLERANT_DIR_LOG_TYPE);
267     _fx_utility_16_unsigned_write( source_buffer + 2, 4096);
268     _fx_utility_32_unsigned_write( source_buffer + 4, 0); /* sector_offset = 0 */
269     _fx_utility_64_unsigned_write( source_buffer + 8, 0); /* log sector = 0 */
270     status = _fx_fault_tolerant_apply_logs( &ram_disk);
271     return_if_fail( status == FX_FILE_CORRUPT);
272 
273     /* _fx_fault_tolerant_add_dir_log always return FX_SUCCESS when data_size(the fourth argument) is zero. */
274     status = _fx_fault_tolerant_add_dir_log( &ram_disk, 0, 0, FX_NULL, 0);
275     return_if_fail( status == FX_SUCCESS);
276 
277     /* The size of a log overflow the size of log file. */
278     ram_disk.fx_media_fault_tolerant_total_logs = 1;
279     source_buffer = ram_disk.fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
280     _fx_utility_16_unsigned_write( source_buffer + 2, 0xffff);
281     status = _fx_fault_tolerant_read_directory_sector( &ram_disk, 0, FX_NULL, 0);
282     return_if_fail( status == FX_FILE_CORRUPT);
283 
284     /* The size of a dir log is larger than a sector which is invalid. */
285     ram_disk.fx_media_fault_tolerant_file_size = 1024;
286     ram_disk.fx_media_fault_tolerant_total_logs = 1;
287     source_buffer = ram_disk.fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
288     _fx_utility_16_unsigned_write( source_buffer, FX_FAULT_TOLERANT_DIR_LOG_TYPE);
289     _fx_utility_16_unsigned_write( source_buffer + 2, 512);
290     _fx_utility_32_unsigned_write( source_buffer + 4, 0); /* sector_offset = 0 */
291     _fx_utility_64_unsigned_write( source_buffer + 8, 0); /* log sector = 0 */
292     status = _fx_fault_tolerant_read_directory_sector( &ram_disk, 0, FX_NULL, 1);
293     return_if_fail( status == FX_FILE_CORRUPT);
294 
295     /* The size of a log overflow the size of log file. */
296     ram_disk.fx_media_fault_tolerant_total_logs = 1;
297     ram_disk.fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_STARTED;
298     source_buffer = ram_disk.fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
299     _fx_utility_16_unsigned_write( source_buffer + 2, 0xffff);
300     status = _fx_utility_logical_sector_read( &ram_disk, 2, ram_disk.fx_media_memory_buffer, 1, FX_DIRECTORY_SECTOR);
301     return_if_fail( status == FX_FILE_CORRUPT);
302 
303     _fx_fault_tolerant_recover( &ram_disk);
304 
305     /* Make a mistake in fx_utility_sector_read.c the last time calling _fx_utility_logical_sector_cache_entry_read. */
306     _fx_utility_logical_sector_read_1_error_request = 1;
307     status = _fx_utility_logical_sector_read( &ram_disk, 99, buffer, 1, FX_DIRECTORY_SECTOR);
308     return_if_fail( status == FX_SUCCESS);
309 
310     status = fx_file_create( &ram_disk, "test.txt");
311     status += fx_file_open( &ram_disk, &my_file, "test.txt", FX_OPEN_FOR_WRITE);
312     status += fx_file_allocate( &my_file, 2048 * 3);
313     status += fx_file_close( &my_file);
314     return_if_fail( status == FX_SUCCESS);
315 
316     /* Register a bad fat entry in cache for the last cluster of the file. */
317     ram_disk.fx_media_fat_cache[28].fx_fat_cache_entry_cluster = 39;
318     ram_disk.fx_media_fat_cache[28].fx_fat_cache_entry_value = 1;
319 
320     /* File corruption is found while calling fx_file_open. */
321     status = fx_file_open( &ram_disk, &my_file, "test.txt", FX_OPEN_FOR_WRITE);
322     return_if_fail( status == FX_FILE_CORRUPT);
323 
324     status = fx_file_create( &ram_disk, "aa");
325     status += fx_file_open( &ram_disk, &my_file, "aa", FX_OPEN_FOR_WRITE);
326     status += fx_file_write( &my_file, read_buffer, 2048 * 3);
327     return_if_fail( status == FX_SUCCESS);
328 
329     bytes_per_cluster = ram_disk.fx_media_bytes_per_sector * ram_disk.fx_media_sectors_per_cluster;
330     clusters = (FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE + bytes_per_cluster - 1) / bytes_per_cluster;
331     cluster = 40 + clusters;
332 
333 #ifndef FX_DISABLE_CACHE
334     /* Register a bad fat entry in cache in the middle of the file. */
335     ram_disk.fx_media_fat_cache[(cluster & FX_FAT_CACHE_HASH_MASK) * FX_FAT_CACHE_DEPTH].fx_fat_cache_entry_cluster = cluster;
336     ram_disk.fx_media_fat_cache[(cluster & FX_FAT_CACHE_HASH_MASK) * FX_FAT_CACHE_DEPTH].fx_fat_cache_entry_value = 0xffff;
337     status += fx_file_seek( &my_file, 2047);
338     status += fx_file_read( &my_file, read_buffer, 5, &actual);
339     return_if_fail( status == FX_FILE_CORRUPT);
340 #endif
341 
342     status = fx_file_close( &my_file);
343     return_if_fail( status == FX_SUCCESS);
344 
345     status = fx_file_create( &ram_disk, "tt");
346     status += fx_file_open( &ram_disk, &my_file, "tt", FX_OPEN_FOR_WRITE);
347     status += fx_file_allocate( &my_file, 2048 * 3);
348     return_if_fail( status == FX_SUCCESS);
349 
350     /* Attempt to cover the branch at the end of fx_file_extended_truncate */
351     /* that size >= file_ptr -> fx_file_maximum_size_used. */
352     my_file.fx_file_maximum_size_used = 0;
353     status = fx_file_extended_truncate( &my_file, 2048);
354     status += fx_file_close( &my_file);
355     return_if_fail( status == FX_SUCCESS);
356 
357     status = fx_file_create( &ram_disk, "test");
358     status += fx_file_open( &ram_disk, &my_file, "test", FX_OPEN_FOR_WRITE);
359     status += fx_file_allocate( &my_file, 2048);
360     return_if_fail( status == FX_SUCCESS);
361 
362     /* Cover the branch in fx_file_extended_truncate_release that fx_file_current_offset <= fx_file_current_file_size. */
363     status = fx_file_seek( &my_file, 0);
364     status += fx_file_extended_truncate_release( &my_file, 1024);
365     return_if_fail( status == FX_SUCCESS);
366 
367     /* Just cover the branch of FX_UTILITY_LOGICAL_SECTOR_READ_EXTENSION_1. */
368     _fx_utility_logical_sector_read_1_error_request = 2;
369     status = _fx_utility_logical_sector_read( &ram_disk, 99, buffer, 1, FX_DIRECTORY_SECTOR);
370 
371     /* Attempt to cover the last branch in _fx_unicode_directory_entry_read that cluster < FX_FAT_ENTRY_START. */
372     uentry = 129;
373     dir_entry1.fx_dir_entry_cluster = 2;
374     unicode_size = fx_unicode_length_get( unicode_name_A1);
375 
376     /* Register an uncorrent fat cache to satisfy cluster < FX_FAT_ENTRY_START. */
377     ram_disk.fx_media_fat_cache[8].fx_fat_cache_entry_cluster = 2;
378     ram_disk.fx_media_fat_cache[8].fx_fat_cache_entry_value = 1;
379 
380     /* Make an IO error to return from the function earlier avoiding core dump. */
381     _fx_utility_logical_sector_read_error_request = 1;
382     status = _fx_unicode_directory_entry_read( &ram_disk, &dir_entry1, &uentry, &dir_entry2,
383            unicode_name_A1, &unicode_size);
384     return_if_fail( status == FX_FILE_CORRUPT);
385 
386     /* Modify fault tolerant FAT chain in buffer. */
387     FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(ram_disk.fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
388     _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new, 3);
389     _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_next_deletion, ram_disk.fx_media_fat_reserved + 1);
390 
391     /* Get fx_fault_tolerant_FAT_chain_next_deletion while looping to cleanup FAT entries. */
392     status = _fx_fault_tolerant_cleanup_FAT_chain( &ram_disk, FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER);
393     return_if_fail( status == FX_SUCCESS);
394 
395     /* Modify fault tolerant FAT chain in buffer. */
396     FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(ram_disk.fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
397     _fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new, 3);
398     _fx_utility_FAT_entry_write(&ram_disk, 3, 1);
399 
400     /* Get fx_fault_tolerant_FAT_chain_next_deletion while looping to cleanup FAT entries. */
401     status = _fx_fault_tolerant_cleanup_FAT_chain( &ram_disk, FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER);
402     return_if_fail( status == FX_SUCCESS);
403 
404     /* Output successful.  */
405     printf("SUCCESS!\n");
406     test_control_return(0);
407 }
408 
409 #else
410 
411 #ifdef CTEST
test_application_define(void * first_unused_memory)412 void test_application_define(void *first_unused_memory)
413 #else
414 void    filex_fault_tolerant_enable_2_test_application_define(void *first_unused_memory)
415 #endif
416 {
417 
418     FX_PARAMETER_NOT_USED(first_unused_memory);
419 
420     /* Print out some test information banners.  */
421     printf("FileX Test:   Fault Tolerant Enable 2 Test...........................N/A\n");
422 
423     test_control_return(255);
424 }
425 #endif
426