1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   Storage Class                                                       */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_host_class_storage.h"
30 #include "ux_host_stack.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_host_class_storage_media_mount                  PORTABLE C      */
38 /*                                                           6.1.9        */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function tries to read the first sector on the media. It then  */
46 /*    determines if this is a partition sector or a boot sector. If the   */
47 /*    sector contains partition information, each partition is checked    */
48 /*    for a DOS aware partition and mounted by UX_MEDIA (default FileX).  */
49 /*                                                                        */
50 /*    If there is no partition sector or boot sector, we simply inform    */
51 /*    UX_MEDIA (default FileX) that a device is present and that its boot */
52 /*    sector  should be periodically read to see if the device is mounted.*/
53 /*    This mechanism applies to storage where the media can be removed    */
54 /*    (floppy, ZIP, flash/smart media readers).                           */
55 /*                                                                        */
56 /*  INPUT                                                                 */
57 /*                                                                        */
58 /*    storage                               Pointer to storage class      */
59 /*    sector                                Boot sector start             */
60 /*                                                                        */
61 /*  OUTPUT                                                                */
62 /*                                                                        */
63 /*    Completion Status                                                   */
64 /*                                                                        */
65 /*  CALLS                                                                 */
66 /*                                                                        */
67 /*    _ux_host_class_storage_media_mount    Mount media                   */
68 /*    _ux_host_class_storage_media_open     Open media                    */
69 /*    _ux_host_class_storage_partition_read Read partition                */
70 /*    _ux_host_class_storage_media_read     Read sectors of media         */
71 /*    _ux_host_class_storage_start_stop     Start the media               */
72 /*    _ux_host_class_storage_unit_ready_test                              */
73 /*                                          Test unit ready               */
74 /*    _ux_utility_memory_allocate           Allocate memory block         */
75 /*    _ux_utility_memory_free               Release memory block          */
76 /*    _ux_utility_short_get                 Get 16-bit value              */
77 /*                                                                        */
78 /*  CALLED BY                                                             */
79 /*                                                                        */
80 /*    Storage Class                                                       */
81 /*                                                                        */
82 /*  RELEASE HISTORY                                                       */
83 /*                                                                        */
84 /*    DATE              NAME                      DESCRIPTION             */
85 /*                                                                        */
86 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
87 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
88 /*                                            added option to disable FX  */
89 /*                                            media integration,          */
90 /*                                            resulting in version 6.1    */
91 /*  10-15-2021     Chaoqiong Xiao           Modified comment(s),          */
92 /*                                            fixed exFAT mounting,       */
93 /*                                            resulting in version 6.1.9  */
94 /*                                                                        */
95 /**************************************************************************/
_ux_host_class_storage_media_mount(UX_HOST_CLASS_STORAGE * storage,ULONG sector)96 UINT  _ux_host_class_storage_media_mount(UX_HOST_CLASS_STORAGE *storage, ULONG sector)
97 {
98 
99 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
100     UX_PARAMETER_NOT_USED(storage);
101     UX_PARAMETER_NOT_USED(sector);
102     return(UX_FUNCTION_NOT_SUPPORTED);
103 #else
104 UCHAR           *sector_memory;
105 UINT            status;
106 
107     /* If trace is enabled, insert this event into the trace buffer.  */
108     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_MOUNT, storage, sector, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
109 
110 #ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
111     /* If the device is UFI, we need to start it.  */
112     if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_STORAGE_PROTOCOL_CBI)
113     {
114 
115         /* Start the media.  */
116         status =  _ux_host_class_storage_start_stop(storage, UX_HOST_CLASS_STORAGE_START_MEDIA);
117 
118         /* Check the status. If the device does not start, fail the operation.
119            But we still return SUCCESS otherwise the storage thread has no chance to inspect this instance.  */
120         if (status != UX_SUCCESS)
121             return(UX_SUCCESS);
122     }
123 #endif
124 
125     /* Obtain memory for reading the partition sector, we do not use the storage instance
126        memory because this function is reentrant.  */
127     sector_memory =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, storage -> ux_host_class_storage_sector_size);
128     if (sector_memory == UX_NULL)
129         return(UX_MEMORY_INSUFFICIENT);
130 
131     /* Check if the device is now ready.  */
132     status =  _ux_host_class_storage_unit_ready_test(storage);
133 
134     /* Check the status. There may be a transport error or the device is not ready.  */
135     if (status == UX_SUCCESS)
136 
137         /* Read the very first sector from the media.  */
138         status =  _ux_host_class_storage_media_read(storage, sector, 1, sector_memory);
139 
140     /* Check the status. There may be a transport error or the device is not ready.  */
141     if (status != UX_SUCCESS)
142     {
143 
144         /* In any case, we free the sector memory.  */
145         _ux_utility_memory_free(sector_memory);
146 
147         if (status == UX_HOST_CLASS_STORAGE_SENSE_ERROR)
148 
149             /* The media is not there, so we will try to check for it at the storage
150                thread level every x seconds.  */
151             return(UX_SUCCESS);
152 
153         /* Since there was a transport error or command error, we do not try to mount
154            a fake media.  */
155         return(status);
156     }
157 
158     /* We need to examine this sector and determine if this is a partition sector
159        or a boot sector.  */
160     if (_ux_utility_short_get(sector_memory + 510) == UX_HOST_CLASS_STORAGE_PARTITION_SIGNATURE)
161     {
162 
163         /* If we have a signature, we know it is a valid media and it may be formatted.
164            If there is no signature, the media exist but maybe not formatted. Now determine
165            if this is a boot sector. The boot sector has a special signature in the first
166            couple of bytes.
167            BUT !!! The first boot sector of an iPod is actually a partition, so we need to
168            look further and see if the number of sector per FAT and the first partition are
169            set to 0. This will indicate a partition sector. Though exFAT has no BIOS parameters
170            block and should be excluded in this case.
171            */
172         if ((*sector_memory == 0xe9) || ((*sector_memory == 0xeb) && *(sector_memory + 2) == 0x90))
173         {
174 
175             /* Check for fake boot sector.  */
176             if (_ux_utility_short_get(sector_memory + 0x16) != 0x0 ||
177                 _ux_utility_long_get(sector_memory + 0x24) != 0x0 ||
178                 (*(sector_memory + 1) == 0x76) /* exFAT volume  */)
179             {
180 
181                 /* This is a boot sector signature.  */
182                 _ux_host_class_storage_media_open(storage, sector);
183                 _ux_utility_memory_free(sector_memory);
184                 return(UX_SUCCESS);
185             }
186         }
187 
188         _ux_host_class_storage_partition_read(storage, sector_memory, sector);
189         _ux_utility_memory_free(sector_memory);
190         return(UX_SUCCESS);
191     }
192     else
193     {
194 
195         /* The drive does not contain a partition table or FAT MBR at LBA 0*/
196         status =  UX_ERROR;
197     }
198 
199     /* Free all resources used.  */
200     _ux_utility_memory_free(sector_memory);
201 
202     /* Return completion status.  */
203     return(status);
204 #endif /* !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) */
205 }
206