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