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 /** USBX Component                                                        */
16 /**                                                                       */
17 /**   Storage Class                                                       */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary system files.  */
24 
25 #define UX_SOURCE_CODE
26 
27 #include "ux_api.h"
28 #include "ux_host_class_storage.h"
29 #include "ux_host_stack.h"
30 
31 
32 /* Defined if FileX is not integrated in USBX
33    and it's used as external module for file system.  */
34 
35 /* #define UX_HOST_CLASS_STORAGE_EXT_FILEX */
36 
37 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
38 
39 #ifdef FX_API_H /* For test, confirm FX is not included before.  */
40 #error fx_api.h should not be included in this mode
41 #endif
42 
43 /* FX not integrated in UX, but used as external module.  */
44 #if defined(UX_HOST_CLASS_STORAGE_EXT_FILEX)
45 
46 /* FX related things needs define here.  */
47 #include "fx_api.h"
48 #define UX_MEDIA                                    FX_MEDIA
49 VOID    _ux_host_class_storage_driver_entry(UX_MEDIA *media);
50 
51 /* FX driver is available to support FX as external module.  */
52 #ifndef UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
53 #define UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
54 #endif
55 #endif
56 #else
57 
58 /* FX driver is used for RTOS mode by default.  */
59 #ifndef UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
60 #define UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
61 #endif
62 #endif
63 
64 
65 #if defined(UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE)
66 /**************************************************************************/
67 /*                                                                        */
68 /*  FUNCTION                                               RELEASE        */
69 /*                                                                        */
70 /*    _ux_host_class_storage_driver_entry                 PORTABLE C      */
71 /*                                                           6.1.12       */
72 /*  AUTHOR                                                                */
73 /*                                                                        */
74 /*    Chaoqiong Xiao, Microsoft Corporation                               */
75 /*                                                                        */
76 /*  DESCRIPTION                                                           */
77 /*                                                                        */
78 /*    This function is the entry point for the FileX file system. All     */
79 /*    FileX driver I/O calls are are multiplexed here and rerouted to     */
80 /*    the proper USB storage class functions.                             */
81 /*                                                                        */
82 /*    When the entry is for storage with FX support (not in standalone    */
83 /*    mode, and with FileX), the FX media is openned in storage mount     */
84 /*    flow, and can be directly used in application after mounted.        */
85 /*                                                                        */
86 /*    When the entry is for no FX mode (FX in external module, and USBX   */
87 /*    is compiled without FileX integration), it is an example with       */
88 /*    disk partition support. In this case the FX media does not operate  */
89 /*    inside the storage flow. Actions are taken when application mounts  */
90 /*    media to FX_MEDIA and then have access to media APIs.               */
91 /*                                                                        */
92 /*    In no FX mode demo, it assumes media is managed with partition      */
93 /*    start from sector address of FX_MEDIA::fx_media_reserved_for_user.  */
94 /*                                                                        */
95 /*    The following links are not initialized in no FX mode, they must be */
96 /*    initialized before using the entry in no FX mode:                   */
97 /*    - FX_MEDIA::fx_media_reserved_for_user                              */
98 /*                                          Partition start sector inside */
99 /*                                          the whole storage media, must */
100 /*                                          set before media open         */
101 /*    - FX_MEDIA::fx_media_driver_info      Pointer to storage media,     */
102 /*                                          assigned while calling media  */
103 /*                                          open (fx_media_open)          */
104 /*                                                                        */
105 /*  INPUT                                                                 */
106 /*                                                                        */
107 /*    media                                 FileX media pointer           */
108 /*                                                                        */
109 /*  OUTPUT                                                                */
110 /*                                                                        */
111 /*    None                                                                */
112 /*                                                                        */
113 /*  CALLS                                                                 */
114 /*                                                                        */
115 /*    _ux_host_class_storage_sense_code_translate                         */
116 /*                                          Translate error status codes  */
117 /*    _ux_host_class_storage_media_read     Read sector(s)                */
118 /*    _ux_host_class_storage_media_write    Write sector(s)               */
119 /*    _ux_host_semaphore_get                Get protection semaphore      */
120 /*    _ux_host_semaphore_put                Release protection semaphore  */
121 /*                                                                        */
122 /*  CALLED BY                                                             */
123 /*                                                                        */
124 /*    FileX                                                               */
125 /*                                                                        */
126 /*  RELEASE HISTORY                                                       */
127 /*                                                                        */
128 /*    DATE              NAME                      DESCRIPTION             */
129 /*                                                                        */
130 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
131 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
132 /*                                            added option to disable FX  */
133 /*                                            media integration,          */
134 /*                                            resulting in version 6.1    */
135 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
136 /*                                            resulting in version 6.1.10 */
137 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
138 /*                                            added implement to support  */
139 /*                                            external FX mode,           */
140 /*                                            resulting in version 6.1.11 */
141 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
142 /*                                            improved external FX mode,  */
143 /*                                            resulting in version 6.1.12 */
144 /*                                                                        */
145 /**************************************************************************/
_ux_host_class_storage_driver_entry(FX_MEDIA * media)146 VOID  _ux_host_class_storage_driver_entry(FX_MEDIA *media)
147 {
148 
149 UINT                            status;
150 UX_HOST_CLASS_STORAGE           *storage;
151 UX_HOST_CLASS_STORAGE_MEDIA     *storage_media;
152 ULONG                           partition_start;
153 
154 
155     /* Get the pointers to the instances and partition start.  */
156 #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
157     storage =  (UX_HOST_CLASS_STORAGE *) media -> fx_media_driver_info;
158     storage_media =  (UX_HOST_CLASS_STORAGE_MEDIA *) media -> fx_media_reserved_for_user;
159     partition_start = storage_media -> ux_host_class_storage_media_partition_start;
160 #else
161     storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) media -> fx_media_driver_info;
162     storage = storage_media -> ux_host_class_storage_media_storage;
163     partition_start = (ULONG) media -> fx_media_reserved_for_user;
164 #endif
165 
166     /* Ensure the instance is valid.  */
167     if ((storage -> ux_host_class_storage_state !=  UX_HOST_CLASS_INSTANCE_LIVE) &&
168         (storage -> ux_host_class_storage_state !=  UX_HOST_CLASS_INSTANCE_MOUNTING))
169     {
170 
171         /* Class instance is invalid. Return an error!  */
172         media -> fx_media_driver_status =  FX_PTR_ERROR;
173         return;
174     }
175 
176 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
177 
178     /* Ensure the media is valid.  */
179     if ((storage_media -> ux_host_class_storage_media_storage != storage) ||
180         (storage_media -> ux_host_class_storage_media_status != UX_USED))
181     {
182 
183         /* Media instance is invalid.  */
184         media -> fx_media_driver_status =  FX_PTR_ERROR;
185         return;
186     }
187 #endif
188 
189     /* Protect Thread reentry to this instance.  */
190     status = _ux_host_class_storage_lock(storage, UX_WAIT_FOREVER);
191     if (status != UX_SUCCESS)
192     {
193 
194         /* Unable to lock, return an error.  */
195         media -> fx_media_driver_status =  FX_INVALID_STATE;
196         return;
197     }
198 
199     /* Restore the LUN number from the media instance.  */
200     storage -> ux_host_class_storage_lun =  storage_media -> ux_host_class_storage_media_lun;
201 
202     /* And the sector size.  */
203     storage -> ux_host_class_storage_sector_size =
204                 storage_media -> ux_host_class_storage_media_sector_size;
205 
206 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
207 
208     /* Restore current used last sector number.  */
209     storage -> ux_host_class_storage_last_sector_number =
210                 storage_media -> ux_host_class_storage_media_number_sectors - 1;
211 #endif
212 
213     /* Look at the request specified by the FileX caller.  */
214     switch (media -> fx_media_driver_request)
215     {
216 
217     case FX_DRIVER_READ:
218 
219         /* Read one or more sectors.  */
220         status =  _ux_host_class_storage_media_read(storage,
221                                 media -> fx_media_driver_logical_sector + partition_start,
222                                 media -> fx_media_driver_sectors,
223                                 media -> fx_media_driver_buffer);
224 
225         /* Check completion status.  */
226         if (status == UX_SUCCESS)
227             media -> fx_media_driver_status =  FX_SUCCESS;
228         else
229         {
230 
231 #if defined(UX_HOST_STANDALONE)
232 
233             /* Poll status.  */
234             _ux_host_class_storage_media_check(storage);
235 #endif
236 
237             media -> fx_media_driver_status =
238                 _ux_host_class_storage_sense_code_translate(storage, status);
239         }
240         break;
241 
242 
243     case FX_DRIVER_WRITE:
244 
245         /* Write one or more sectors.  */
246         status =  _ux_host_class_storage_media_write(storage,
247                                 media -> fx_media_driver_logical_sector + partition_start,
248                                 media -> fx_media_driver_sectors,
249                                 media -> fx_media_driver_buffer);
250 
251         /* Check completion status.  */
252         if (status == UX_SUCCESS)
253             media -> fx_media_driver_status =  FX_SUCCESS;
254         else
255         {
256 
257 #if defined(UX_HOST_STANDALONE)
258 
259             /* Poll status.  */
260             _ux_host_class_storage_media_check(storage);
261 #endif
262 
263             media -> fx_media_driver_status =
264                 _ux_host_class_storage_sense_code_translate(storage,status);
265         }
266         break;
267 
268 
269     case FX_DRIVER_FLUSH:
270 
271         /* Nothing to do. Just return a good status!  */
272         media -> fx_media_driver_status =  FX_SUCCESS;
273         break;
274 
275 
276     case FX_DRIVER_ABORT:
277 
278         /* Nothing to do. Just return a good status!  */
279         media -> fx_media_driver_status =  FX_SUCCESS;
280         break;
281 
282 
283     case FX_DRIVER_INIT:
284 
285 #if defined(UX_HOST_STANDALONE)
286 
287             /* Poll status.  */
288             _ux_host_class_storage_media_check(storage);
289 #endif
290 
291         /* Check for media protection.  We must do this operation here because FileX clears all the
292            media fields before init.  */
293         if (storage -> ux_host_class_storage_write_protected_media ==  UX_TRUE)
294 
295             /* The media is Write Protected. We tell FileX.  */
296             media -> fx_media_driver_write_protect = UX_TRUE;
297 
298         /* This function always succeeds.  */
299         media -> fx_media_driver_status =  FX_SUCCESS;
300         break;
301 
302 
303     case FX_DRIVER_UNINIT:
304 
305         /* Nothing to do. Just return a good status!  */
306         media -> fx_media_driver_status =  FX_SUCCESS;
307         break;
308 
309 
310     case FX_DRIVER_BOOT_READ:
311 
312         /* Read the media boot sector.  */
313         status =  _ux_host_class_storage_media_read(storage,
314                 partition_start, 1, media -> fx_media_driver_buffer);
315 
316         /* Check completion status.  */
317         if (status == UX_SUCCESS)
318             media -> fx_media_driver_status =  FX_SUCCESS;
319         else
320         {
321 
322 #if defined(UX_HOST_STANDALONE)
323 
324             /* Poll status.  */
325             _ux_host_class_storage_media_check(storage);
326 #endif
327 
328             media -> fx_media_driver_status =
329                 _ux_host_class_storage_sense_code_translate(storage,status);
330         }
331         break;
332 
333 
334     case FX_DRIVER_BOOT_WRITE:
335 
336         /* Write the boot sector.  */
337         status =  _ux_host_class_storage_media_write(storage,
338                 partition_start, 1, media -> fx_media_driver_buffer);
339 
340         /* Check completion status.  */
341         if (status == UX_SUCCESS)
342             media -> fx_media_driver_status =  FX_SUCCESS;
343         else
344         {
345 
346 #if defined(UX_HOST_STANDALONE)
347 
348             /* Poll status.  */
349             _ux_host_class_storage_media_check(storage);
350 #endif
351 
352             media -> fx_media_driver_status =
353                 _ux_host_class_storage_sense_code_translate(storage,status);
354         }
355         break;
356 
357 
358     default:
359 
360         /* Invalid request from FileX */
361         media -> fx_media_driver_status =  FX_IO_ERROR;
362         break;
363     }
364 
365     /* Unprotect thread reentry to this instance.  */
366     _ux_host_class_storage_unlock(storage);
367 }
368 #endif
369