summaryrefslogtreecommitdiff
path: root/common/usbx_host_classes/src/ux_host_class_storage_media_mount.c
blob: d43bbd6c02cb55e5484218274af72afea290cf63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/***************************************************************************
 * Copyright (c) 2024 Microsoft Corporation
 * Copyright (c) 2026-present Eclipse ThreadX contributors
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * SPDX-License-Identifier: MIT
 **************************************************************************/


/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** USBX Component                                                        */
/**                                                                       */
/**   Storage Class                                                       */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/


/* Include necessary system files.  */

#define UX_SOURCE_CODE

#include "ux_api.h"
#include "ux_host_class_storage.h"
#include "ux_host_stack.h"


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _ux_host_class_storage_media_mount                  PORTABLE C      */
/*                                                           6.1.9        */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Chaoqiong Xiao, Microsoft Corporation                               */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function tries to read the first sector on the media. It then  */
/*    determines if this is a partition sector or a boot sector. If the   */
/*    sector contains partition information, each partition is checked    */
/*    for a DOS aware partition and mounted by UX_MEDIA (default FileX).  */
/*                                                                        */
/*    If there is no partition sector or boot sector, we simply inform    */
/*    UX_MEDIA (default FileX) that a device is present and that its boot */
/*    sector  should be periodically read to see if the device is mounted.*/
/*    This mechanism applies to storage where the media can be removed    */
/*    (floppy, ZIP, flash/smart media readers).                           */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    storage                               Pointer to storage class      */
/*    sector                                Boot sector start             */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    Completion Status                                                   */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _ux_host_class_storage_media_mount    Mount media                   */
/*    _ux_host_class_storage_media_open     Open media                    */
/*    _ux_host_class_storage_partition_read Read partition                */
/*    _ux_host_class_storage_media_read     Read sectors of media         */
/*    _ux_host_class_storage_start_stop     Start the media               */
/*    _ux_host_class_storage_unit_ready_test                              */
/*                                          Test unit ready               */
/*    _ux_utility_memory_allocate           Allocate memory block         */
/*    _ux_utility_memory_free               Release memory block          */
/*    _ux_utility_short_get                 Get 16-bit value              */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Storage Class                                                       */
/*                                                                        */
/**************************************************************************/
UINT  _ux_host_class_storage_media_mount(UX_HOST_CLASS_STORAGE *storage, ULONG sector)
{

#if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
    UX_PARAMETER_NOT_USED(storage);
    UX_PARAMETER_NOT_USED(sector);
    return(UX_FUNCTION_NOT_SUPPORTED);
#else
UCHAR           *sector_memory;
UINT            status;

    /* If trace is enabled, insert this event into the trace buffer.  */
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_MOUNT, storage, sector, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)

#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
    /* If the device is UFI, we need to start it.  */
    if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_STORAGE_PROTOCOL_CBI)
    {

        /* Start the media.  */
        status =  _ux_host_class_storage_start_stop(storage, UX_HOST_CLASS_STORAGE_START_MEDIA);

        /* Check the status. If the device does not start, fail the operation.
           But we still return SUCCESS otherwise the storage thread has no chance to inspect this instance.  */
        if (status != UX_SUCCESS)
            return(UX_SUCCESS);
    }
#endif

    /* Obtain memory for reading the partition sector, we do not use the storage instance
       memory because this function is reentrant.  */
    sector_memory =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, storage -> ux_host_class_storage_sector_size);
    if (sector_memory == UX_NULL)
        return(UX_MEMORY_INSUFFICIENT);

    /* Check if the device is now ready.  */
    status =  _ux_host_class_storage_unit_ready_test(storage);

    /* Check the status. There may be a transport error or the device is not ready.  */
    if (status == UX_SUCCESS)

        /* Read the very first sector from the media.  */
        status =  _ux_host_class_storage_media_read(storage, sector, 1, sector_memory);

    /* Check the status. There may be a transport error or the device is not ready.  */
    if (status != UX_SUCCESS)
    {

        /* In any case, we free the sector memory.  */
        _ux_utility_memory_free(sector_memory);

        if (status == UX_HOST_CLASS_STORAGE_SENSE_ERROR)

            /* The media is not there, so we will try to check for it at the storage
               thread level every x seconds.  */
            return(UX_SUCCESS);

        /* Since there was a transport error or command error, we do not try to mount
           a fake media.  */
        return(status);
    }

    /* We need to examine this sector and determine if this is a partition sector
       or a boot sector.  */
    if (_ux_utility_short_get(sector_memory + 510) == UX_HOST_CLASS_STORAGE_PARTITION_SIGNATURE)
    {

        /* If we have a signature, we know it is a valid media and it may be formatted.
           If there is no signature, the media exist but maybe not formatted. Now determine
           if this is a boot sector. The boot sector has a special signature in the first
           couple of bytes.
           BUT !!! The first boot sector of an iPod is actually a partition, so we need to
           look further and see if the number of sector per FAT and the first partition are
           set to 0. This will indicate a partition sector. Though exFAT has no BIOS parameters
           block and should be excluded in this case.
           */
        if ((*sector_memory == 0xe9) || ((*sector_memory == 0xeb) && *(sector_memory + 2) == 0x90))
        {

            /* Check for fake boot sector.  */
            if (_ux_utility_short_get(sector_memory + 0x16) != 0x0 ||
                _ux_utility_long_get(sector_memory + 0x24) != 0x0 ||
                (*(sector_memory + 1) == 0x76) /* exFAT volume  */)
            {

                /* This is a boot sector signature.  */
                _ux_host_class_storage_media_open(storage, sector);
                _ux_utility_memory_free(sector_memory);
                return(UX_SUCCESS);
            }
        }

        _ux_host_class_storage_partition_read(storage, sector_memory, sector);
        _ux_utility_memory_free(sector_memory);
        return(UX_SUCCESS);
    }
    else
    {

        /* The drive does not contain a partition table or FAT MBR at LBA 0*/
        status =  UX_ERROR;
    }

    /* Free all resources used.  */
    _ux_utility_memory_free(sector_memory);

    /* Return completion status.  */
    return(status);
#endif /* !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) */
}