]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
MdeModulePkg/PartitionDxe: remove always false comparison
[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 UINT32 RemainderByMediaBlockSize;
247 EFI_STATUS Status;
248 EFI_BLOCK_IO_MEDIA *Media;
249 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
250 EFI_GUID *VendorDefinedGuid;
251 EFI_GUID UdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;
252 EFI_PARTITION_INFO_PROTOCOL PartitionInfo;
253
254 Media = BlockIo->Media;
255
256 //
257 // Check if UDF logical block size is multiple of underlying device block size
258 //
259 DivU64x32Remainder (
260 UDF_LOGICAL_SECTOR_SIZE, // Dividend
261 Media->BlockSize, // Divisor
262 &RemainderByMediaBlockSize // Remainder
263 );
264 if (RemainderByMediaBlockSize != 0) {
265 return EFI_NOT_FOUND;
266 }
267
268 DevicePathNode = DevicePath;
269 while (!IsDevicePathEnd (DevicePathNode)) {
270 //
271 // Do not allow checking for UDF file systems in CDROM "El Torito"
272 // partitions, and skip duplicate installation of UDF file system child
273 // nodes.
274 //
275 if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) {
276 if (DevicePathSubType (DevicePathNode) == MEDIA_CDROM_DP) {
277 return EFI_NOT_FOUND;
278 }
279 if (DevicePathSubType (DevicePathNode) == MEDIA_VENDOR_DP) {
280 VendorDefinedGuid = (EFI_GUID *)((UINTN)DevicePathNode +
281 OFFSET_OF (VENDOR_DEVICE_PATH, Guid));
282 if (CompareGuid (VendorDefinedGuid, &UdfDevPathGuid)) {
283 return EFI_NOT_FOUND;
284 }
285 }
286 }
287 //
288 // Try next device path node
289 //
290 DevicePathNode = NextDevicePathNode (DevicePathNode);
291 }
292
293 //
294 // Check if block device supports an UDF file system
295 //
296 Status = SupportUdfFileSystem (BlockIo, DiskIo);
297 if (EFI_ERROR (Status)) {
298 return EFI_NOT_FOUND;
299 }
300
301 //
302 // Create Partition Info protocol for UDF file system
303 //
304 ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
305 PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
306 PartitionInfo.Type = PARTITION_TYPE_OTHER;
307
308 //
309 // Install partition child handle for UDF file system
310 //
311 Status = PartitionInstallChildHandle (
312 This,
313 Handle,
314 DiskIo,
315 DiskIo2,
316 BlockIo,
317 BlockIo2,
318 DevicePath,
319 (EFI_DEVICE_PATH_PROTOCOL *)&gUdfDevicePath,
320 &PartitionInfo,
321 0,
322 Media->LastBlock,
323 Media->BlockSize
324 );
325 if (!EFI_ERROR (Status)) {
326 Status = EFI_NOT_FOUND;
327 }
328
329 return Status;
330 }