]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
MdeModulePkg/PartitionDxe: Initialize the array after declaration
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / PartitionDxe / Udf.c
1 /** @file
2 Scan for an UDF file system on a formatted media.
3
4 Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
5
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
12 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 **/
14
15 #include "Partition.h"
16
17 //
18 // C5BD4D42-1A76-4996-8956-73CDA326CD0A
19 //
20 #define EFI_UDF_DEVICE_PATH_GUID \
21 { 0xC5BD4D42, 0x1A76, 0x4996, \
22 { 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A } \
23 }
24
25 typedef struct {
26 VENDOR_DEVICE_PATH DevicePath;
27 EFI_DEVICE_PATH_PROTOCOL End;
28 } UDF_DEVICE_PATH;
29
30 //
31 // Vendor-Defined Media Device Path for UDF file system
32 //
33 UDF_DEVICE_PATH gUdfDevicePath = {
34 { { MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,
35 { sizeof (VENDOR_DEVICE_PATH), 0 } },
36 EFI_UDF_DEVICE_PATH_GUID
37 },
38 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
39 { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
40 }
41 };
42
43 EFI_STATUS
44 FindAnchorVolumeDescriptorPointer (
45 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
46 IN EFI_DISK_IO_PROTOCOL *DiskIo,
47 OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint
48 )
49 {
50 EFI_STATUS Status;
51 UINT32 BlockSize;
52 EFI_LBA EndLBA;
53 EFI_LBA DescriptorLBAs[4];
54 UINTN Index;
55
56 BlockSize = BlockIo->Media->BlockSize;
57 EndLBA = BlockIo->Media->LastBlock;
58 DescriptorLBAs[0] = 256;
59 DescriptorLBAs[1] = EndLBA - 256;
60 DescriptorLBAs[2] = EndLBA;
61 DescriptorLBAs[3] = 512;
62
63 for (Index = 0; Index < ARRAY_SIZE (DescriptorLBAs); Index++) {
64 Status = DiskIo->ReadDisk (
65 DiskIo,
66 BlockIo->Media->MediaId,
67 MultU64x32 (DescriptorLBAs[Index], BlockSize),
68 sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),
69 (VOID *)AnchorPoint
70 );
71 if (EFI_ERROR (Status)) {
72 return Status;
73 }
74 //
75 // Check if read LBA has a valid AVDP descriptor.
76 //
77 if (IS_AVDP (AnchorPoint)) {
78 return EFI_SUCCESS;
79 }
80 }
81 //
82 // No AVDP found.
83 //
84 return EFI_VOLUME_CORRUPTED;
85 }
86
87 /**
88 Check if block device supports a valid UDF file system as specified by OSTA
89 Universal Disk Format Specification 2.60.
90
91 @param[in] BlockIo BlockIo interface.
92 @param[in] DiskIo DiskIo interface.
93
94 @retval EFI_SUCCESS UDF file system found.
95 @retval EFI_UNSUPPORTED UDF file system not found.
96 @retval EFI_NO_MEDIA The device has no media.
97 @retval EFI_DEVICE_ERROR The device reported an error.
98 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
99 @retval EFI_OUT_OF_RESOURCES The scan was not successful due to lack of
100 resources.
101
102 **/
103 EFI_STATUS
104 SupportUdfFileSystem (
105 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
106 IN EFI_DISK_IO_PROTOCOL *DiskIo
107 )
108 {
109 EFI_STATUS Status;
110 UINT64 Offset;
111 UINT64 EndDiskOffset;
112 CDROM_VOLUME_DESCRIPTOR VolDescriptor;
113 CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor;
114 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;
115
116 ZeroMem ((VOID *)&TerminatingVolDescriptor, sizeof (CDROM_VOLUME_DESCRIPTOR));
117
118 //
119 // Start Volume Recognition Sequence
120 //
121 EndDiskOffset = MultU64x32 (BlockIo->Media->LastBlock,
122 BlockIo->Media->BlockSize);
123
124 for (Offset = UDF_VRS_START_OFFSET; Offset < EndDiskOffset;
125 Offset += UDF_LOGICAL_SECTOR_SIZE) {
126 //
127 // Check if block device has a Volume Structure Descriptor and an Extended
128 // Area.
129 //
130 Status = DiskIo->ReadDisk (
131 DiskIo,
132 BlockIo->Media->MediaId,
133 Offset,
134 sizeof (CDROM_VOLUME_DESCRIPTOR),
135 (VOID *)&VolDescriptor
136 );
137 if (EFI_ERROR (Status)) {
138 return Status;
139 }
140
141 if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
142 (VOID *)UDF_BEA_IDENTIFIER,
143 sizeof (VolDescriptor.Unknown.Id)) == 0) {
144 break;
145 }
146
147 if ((CompareMem ((VOID *)VolDescriptor.Unknown.Id,
148 (VOID *)CDVOL_ID,
149 sizeof (VolDescriptor.Unknown.Id)) != 0) ||
150 (CompareMem ((VOID *)&VolDescriptor,
151 (VOID *)&TerminatingVolDescriptor,
152 sizeof (CDROM_VOLUME_DESCRIPTOR)) == 0)) {
153 return EFI_UNSUPPORTED;
154 }
155 }
156
157 //
158 // Look for "NSR0{2,3}" identifiers in the Extended Area.
159 //
160 Offset += UDF_LOGICAL_SECTOR_SIZE;
161 if (Offset >= EndDiskOffset) {
162 return EFI_UNSUPPORTED;
163 }
164
165 Status = DiskIo->ReadDisk (
166 DiskIo,
167 BlockIo->Media->MediaId,
168 Offset,
169 sizeof (CDROM_VOLUME_DESCRIPTOR),
170 (VOID *)&VolDescriptor
171 );
172 if (EFI_ERROR (Status)) {
173 return Status;
174 }
175
176 if ((CompareMem ((VOID *)VolDescriptor.Unknown.Id,
177 (VOID *)UDF_NSR2_IDENTIFIER,
178 sizeof (VolDescriptor.Unknown.Id)) != 0) &&
179 (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
180 (VOID *)UDF_NSR3_IDENTIFIER,
181 sizeof (VolDescriptor.Unknown.Id)) != 0)) {
182 return EFI_UNSUPPORTED;
183 }
184
185 //
186 // Look for "TEA01" identifier in the Extended Area
187 //
188 Offset += UDF_LOGICAL_SECTOR_SIZE;
189 if (Offset >= EndDiskOffset) {
190 return EFI_UNSUPPORTED;
191 }
192
193 Status = DiskIo->ReadDisk (
194 DiskIo,
195 BlockIo->Media->MediaId,
196 Offset,
197 sizeof (CDROM_VOLUME_DESCRIPTOR),
198 (VOID *)&VolDescriptor
199 );
200 if (EFI_ERROR (Status)) {
201 return Status;
202 }
203
204 if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
205 (VOID *)UDF_TEA_IDENTIFIER,
206 sizeof (VolDescriptor.Unknown.Id)) != 0) {
207 return EFI_UNSUPPORTED;
208 }
209
210 Status = FindAnchorVolumeDescriptorPointer (BlockIo, DiskIo, &AnchorPoint);
211 if (EFI_ERROR (Status)) {
212 return EFI_UNSUPPORTED;
213 }
214
215 return EFI_SUCCESS;
216 }
217
218 /**
219 Install child handles if the Handle supports UDF/ECMA-167 volume format.
220
221 @param[in] This Calling context.
222 @param[in] Handle Parent Handle.
223 @param[in] DiskIo Parent DiskIo interface.
224 @param[in] DiskIo2 Parent DiskIo2 interface.
225 @param[in] BlockIo Parent BlockIo interface.
226 @param[in] BlockIo2 Parent BlockIo2 interface.
227 @param[in] DevicePath Parent Device Path
228
229
230 @retval EFI_SUCCESS Child handle(s) was added.
231 @retval EFI_MEDIA_CHANGED Media changed Detected.
232 @retval other no child handle was added.
233
234 **/
235 EFI_STATUS
236 PartitionInstallUdfChildHandles (
237 IN EFI_DRIVER_BINDING_PROTOCOL *This,
238 IN EFI_HANDLE Handle,
239 IN EFI_DISK_IO_PROTOCOL *DiskIo,
240 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
241 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
242 IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
243 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
244 )
245 {
246 EFI_STATUS Status;
247 EFI_BLOCK_IO_MEDIA *Media;
248 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
249 EFI_GUID *VendorDefinedGuid;
250 EFI_GUID UdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;
251 EFI_PARTITION_INFO_PROTOCOL PartitionInfo;
252
253 Media = BlockIo->Media;
254
255 //
256 // Check if UDF logical block size is multiple of underlying device block size
257 //
258 if ((UDF_LOGICAL_SECTOR_SIZE % Media->BlockSize) != 0 ||
259 Media->BlockSize > UDF_LOGICAL_SECTOR_SIZE) {
260 return EFI_NOT_FOUND;
261 }
262
263 DevicePathNode = DevicePath;
264 while (!IsDevicePathEnd (DevicePathNode)) {
265 //
266 // Do not allow checking for UDF file systems in CDROM "El Torito"
267 // partitions, and skip duplicate installation of UDF file system child
268 // nodes.
269 //
270 if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) {
271 if (DevicePathSubType (DevicePathNode) == MEDIA_CDROM_DP) {
272 return EFI_NOT_FOUND;
273 }
274 if (DevicePathSubType (DevicePathNode) == MEDIA_VENDOR_DP) {
275 VendorDefinedGuid = (EFI_GUID *)((UINTN)DevicePathNode +
276 OFFSET_OF (VENDOR_DEVICE_PATH, Guid));
277 if (CompareGuid (VendorDefinedGuid, &UdfDevPathGuid)) {
278 return EFI_NOT_FOUND;
279 }
280 }
281 }
282 //
283 // Try next device path node
284 //
285 DevicePathNode = NextDevicePathNode (DevicePathNode);
286 }
287
288 //
289 // Check if block device supports an UDF file system
290 //
291 Status = SupportUdfFileSystem (BlockIo, DiskIo);
292 if (EFI_ERROR (Status)) {
293 return EFI_NOT_FOUND;
294 }
295
296 //
297 // Create Partition Info protocol for UDF file system
298 //
299 ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
300 PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
301 PartitionInfo.Type = PARTITION_TYPE_OTHER;
302
303 //
304 // Install partition child handle for UDF file system
305 //
306 Status = PartitionInstallChildHandle (
307 This,
308 Handle,
309 DiskIo,
310 DiskIo2,
311 BlockIo,
312 BlockIo2,
313 DevicePath,
314 (EFI_DEVICE_PATH_PROTOCOL *)&gUdfDevicePath,
315 &PartitionInfo,
316 0,
317 Media->LastBlock,
318 Media->BlockSize
319 );
320 if (!EFI_ERROR (Status)) {
321 Status = EFI_NOT_FOUND;
322 }
323
324 return Status;
325 }