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_directory.h"
27 #include "fx_fault_tolerant.h"
28 
29 
30 #ifdef FX_ENABLE_FAULT_TOLERANT
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _fx_fault_tolerant_create_log_file                  PORTABLE C      */
36 /*                                                           6.1.11       */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    William E. Lamie, Microsoft Corporation                             */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function finds an available cluster used by log file. Then it  */
44 /*    sets the cluster number to boot sector.                             */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    media_ptr                             Media control block pointer   */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    return status                                                       */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _fx_utility_FAT_entry_read            Read a FAT entry              */
57 /*    _fx_utility_FAT_entry_write           Write a FAT entry             */
58 /*    _fx_utility_FAT_flush                 Flush written FAT entries     */
59 /*    _fx_utility_32_unsigned_write         Write a ULONG from memory     */
60 /*    _fx_utility_logical_sector_read       Read a logical sector         */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    _fx_fault_tolerant_enable                                           */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
71 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
72 /*                                            resulting in version 6.1    */
73 /*  01-31-2022     Bhupendra Naphade        Modified comment(s), replaced */
74 /*                                            sector size constant,       */
75 /*                                            resulting in version 6.1.10 */
76 /*  04-25-2022     William E. Lamie         Modified comment(s),          */
77 /*                                            resulting in version 6.1.11 */
78 /*                                                                        */
79 /**************************************************************************/
_fx_fault_tolerant_create_log_file(FX_MEDIA * media_ptr)80 UINT _fx_fault_tolerant_create_log_file(FX_MEDIA *media_ptr)
81 {
82 ULONG clusters;
83 ULONG FAT_index;
84 ULONG FAT_value = 0;
85 UINT  found;
86 UINT  status;
87 UINT  i;
88 
89     /* Yes. Create a log file. */
90     /* First find a free cluster. */
91     if (media_ptr -> fx_media_available_clusters < media_ptr -> fx_media_fault_tolerant_clusters)
92     {
93 
94         /* Out of disk space.  */
95         return(FX_NO_MORE_SPACE);
96     }
97 
98     /* Now we need to find the consecutive clusters.  */
99     clusters = media_ptr -> fx_media_fault_tolerant_clusters;
100     FAT_index =  FX_FAT_ENTRY_START;
101     found =  FX_FALSE;
102     while (FAT_index <= (media_ptr -> fx_media_total_clusters - clusters + FX_FAT_ENTRY_START))
103     {
104 
105         /* Determine if enough consecutive FAT entries are available.  */
106         i =  0;
107 
108 
109         do
110         {
111 
112             /* Read a FAT entry.  */
113             status =  _fx_utility_FAT_entry_read(media_ptr, (FAT_index + i), &FAT_value);
114 
115             /* Check for a successful status.  */
116             if (status != FX_SUCCESS)
117             {
118 
119                 /* Return the error status.  */
120                 return(status);
121             }
122 
123             /* Determine if the entry is free.  */
124             if (FAT_value != FX_FREE_CLUSTER)
125             {
126                 break;
127             }
128 
129             /* Otherwise, increment the consecutive FAT indices.  */
130             i++;
131         } while (i < clusters);
132 
133         /* Determine if we found enough FAT entries.  */
134         if (i >= clusters)
135         {
136 
137             /* Yes, we have found enough FAT entries - set the found
138                flag and get out of this loop.  */
139             found =  FX_TRUE;
140             break;
141         }
142         else
143         {
144             /* Position to the next possibly free FAT entry.  */
145             FAT_index =  FAT_index + i + 1;
146         }
147     }
148 
149     /* Determine if we found enough consecutive clusters to satisfy the
150        request.  */
151     if (!found)
152     {
153 
154         /* Not enough contiguous space on the media.  Return error status.  */
155         return(FX_NO_MORE_SPACE);
156     }
157 
158     /* Update the link pointers in the new clusters.  */
159     for (i = 0; i < (clusters - 1); i++)
160     {
161 
162         /* Update the cluster links.  Since the allocation is
163            sequential, we just have to link each FAT entry to the
164            next one.  */
165         status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index + i, FAT_index + i + 1);
166 
167         /* Check for a bad status.  */
168         if (status != FX_SUCCESS)
169         {
170 
171             /* Return the error status.  */
172             return(status);
173         }
174 
175     }
176 
177     /* Now place an EOF in the last cluster entry.  */
178     status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index + clusters - 1, media_ptr -> fx_media_fat_last);
179 
180     /* Check for a bad status.  */
181     if (status != FX_SUCCESS)
182     {
183 
184         /* Return the error status.  */
185         return(status);
186     }
187 
188 
189 #ifdef FX_FAULT_TOLERANT
190 
191     /* Flush the cached individual FAT entries */
192     _fx_utility_FAT_flush(media_ptr);
193 
194 #endif /* FX_FAULT_TOLERANT */
195 
196     /* Write start cluster for the file tolerant log file into the boot sector. */
197     _fx_utility_32_unsigned_write(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_BOOT_INDEX, FAT_index);
198 
199     /* Write the boot sector.  */
200     media_ptr -> fx_media_driver_request =       FX_DRIVER_BOOT_WRITE;
201     media_ptr -> fx_media_driver_status =        FX_IO_ERROR;
202     media_ptr -> fx_media_driver_buffer =        media_ptr -> fx_media_fault_tolerant_memory_buffer;
203     media_ptr -> fx_media_driver_sectors =       1;
204     media_ptr -> fx_media_driver_sector_type =   FX_BOOT_SECTOR;
205 
206     /* If trace is enabled, insert this event into the trace buffer.  */
207     FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_WRITE, media_ptr, media_ptr -> fx_media_fault_tolerant_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
208 
209     /* Invoke the driver to read the boot sector.  */
210     (media_ptr -> fx_media_driver_entry) (media_ptr);
211 
212     /* Determine if the boot sector was read correctly. */
213     if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
214     {
215 
216         /* Return the boot sector error status.  */
217         return(FX_BOOT_ERROR);
218     }
219 
220 
221     /* Set the start cluster. */
222     media_ptr -> fx_media_fault_tolerant_start_cluster = FAT_index;
223 
224     /* Decrease available cluster. */
225     media_ptr -> fx_media_available_clusters =
226         media_ptr -> fx_media_available_clusters - clusters;
227 
228     /* Return success.  */
229     return(FX_SUCCESS);
230 }
231 #endif /* FX_ENABLE_FAULT_TOLERANT */
232 
233