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