]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
MdeModulePkg/Udf: Refine function description comments
[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
077f8c43
HW
43/**\r
44 Find the anchor volume descriptor pointer.\r
45\r
46 @param[in] BlockIo BlockIo interface.\r
47 @param[in] DiskIo DiskIo interface.\r
48 @param[out] AnchorPoint Anchor volume descriptor pointer.\r
49\r
50 @retval EFI_SUCCESS Anchor volume descriptor pointer found.\r
51 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
52 @retval other Anchor volume descriptor pointer not found.\r
53\r
54**/\r
8aafec2c
PA
55EFI_STATUS\r
56FindAnchorVolumeDescriptorPointer (\r
57 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
58 IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
59 OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint\r
60 )\r
61{\r
62 EFI_STATUS Status;\r
c05cae55
DB
63 UINT32 BlockSize;\r
64 EFI_LBA EndLBA;\r
65 EFI_LBA DescriptorLBAs[4];\r
8aafec2c
PA
66 UINTN Index;\r
67\r
c05cae55
DB
68 BlockSize = BlockIo->Media->BlockSize;\r
69 EndLBA = BlockIo->Media->LastBlock;\r
70 DescriptorLBAs[0] = 256;\r
71 DescriptorLBAs[1] = EndLBA - 256;\r
72 DescriptorLBAs[2] = EndLBA;\r
73 DescriptorLBAs[3] = 512;\r
74\r
8aafec2c
PA
75 for (Index = 0; Index < ARRAY_SIZE (DescriptorLBAs); Index++) {\r
76 Status = DiskIo->ReadDisk (\r
77 DiskIo,\r
78 BlockIo->Media->MediaId,\r
79 MultU64x32 (DescriptorLBAs[Index], BlockSize),\r
80 sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),\r
81 (VOID *)AnchorPoint\r
82 );\r
83 if (EFI_ERROR (Status)) {\r
84 return Status;\r
85 }\r
86 //\r
87 // Check if read LBA has a valid AVDP descriptor.\r
88 //\r
89 if (IS_AVDP (AnchorPoint)) {\r
90 return EFI_SUCCESS;\r
91 }\r
92 }\r
93 //\r
94 // No AVDP found.\r
95 //\r
96 return EFI_VOLUME_CORRUPTED;\r
97}\r
98\r
99/**\r
100 Check if block device supports a valid UDF file system as specified by OSTA\r
101 Universal Disk Format Specification 2.60.\r
102\r
103 @param[in] BlockIo BlockIo interface.\r
104 @param[in] DiskIo DiskIo interface.\r
105\r
106 @retval EFI_SUCCESS UDF file system found.\r
107 @retval EFI_UNSUPPORTED UDF file system not found.\r
108 @retval EFI_NO_MEDIA The device has no media.\r
109 @retval EFI_DEVICE_ERROR The device reported an error.\r
110 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
111 @retval EFI_OUT_OF_RESOURCES The scan was not successful due to lack of\r
112 resources.\r
113\r
114**/\r
115EFI_STATUS\r
116SupportUdfFileSystem (\r
117 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
118 IN EFI_DISK_IO_PROTOCOL *DiskIo\r
119 )\r
120{\r
121 EFI_STATUS Status;\r
122 UINT64 Offset;\r
123 UINT64 EndDiskOffset;\r
124 CDROM_VOLUME_DESCRIPTOR VolDescriptor;\r
125 CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor;\r
126 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;\r
127\r
128 ZeroMem ((VOID *)&TerminatingVolDescriptor, sizeof (CDROM_VOLUME_DESCRIPTOR));\r
129\r
130 //\r
131 // Start Volume Recognition Sequence\r
132 //\r
133 EndDiskOffset = MultU64x32 (BlockIo->Media->LastBlock,\r
134 BlockIo->Media->BlockSize);\r
135\r
136 for (Offset = UDF_VRS_START_OFFSET; Offset < EndDiskOffset;\r
137 Offset += UDF_LOGICAL_SECTOR_SIZE) {\r
138 //\r
139 // Check if block device has a Volume Structure Descriptor and an Extended\r
140 // Area.\r
141 //\r
142 Status = DiskIo->ReadDisk (\r
143 DiskIo,\r
144 BlockIo->Media->MediaId,\r
145 Offset,\r
146 sizeof (CDROM_VOLUME_DESCRIPTOR),\r
147 (VOID *)&VolDescriptor\r
148 );\r
149 if (EFI_ERROR (Status)) {\r
150 return Status;\r
151 }\r
152\r
153 if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,\r
154 (VOID *)UDF_BEA_IDENTIFIER,\r
155 sizeof (VolDescriptor.Unknown.Id)) == 0) {\r
156 break;\r
157 }\r
158\r
159 if ((CompareMem ((VOID *)VolDescriptor.Unknown.Id,\r
160 (VOID *)CDVOL_ID,\r
161 sizeof (VolDescriptor.Unknown.Id)) != 0) ||\r
162 (CompareMem ((VOID *)&VolDescriptor,\r
163 (VOID *)&TerminatingVolDescriptor,\r
164 sizeof (CDROM_VOLUME_DESCRIPTOR)) == 0)) {\r
165 return EFI_UNSUPPORTED;\r
166 }\r
167 }\r
168\r
169 //\r
170 // Look for "NSR0{2,3}" identifiers in the Extended Area.\r
171 //\r
172 Offset += UDF_LOGICAL_SECTOR_SIZE;\r
173 if (Offset >= EndDiskOffset) {\r
174 return EFI_UNSUPPORTED;\r
175 }\r
176\r
177 Status = DiskIo->ReadDisk (\r
178 DiskIo,\r
179 BlockIo->Media->MediaId,\r
180 Offset,\r
181 sizeof (CDROM_VOLUME_DESCRIPTOR),\r
182 (VOID *)&VolDescriptor\r
183 );\r
184 if (EFI_ERROR (Status)) {\r
185 return Status;\r
186 }\r
187\r
188 if ((CompareMem ((VOID *)VolDescriptor.Unknown.Id,\r
189 (VOID *)UDF_NSR2_IDENTIFIER,\r
190 sizeof (VolDescriptor.Unknown.Id)) != 0) &&\r
191 (CompareMem ((VOID *)VolDescriptor.Unknown.Id,\r
192 (VOID *)UDF_NSR3_IDENTIFIER,\r
193 sizeof (VolDescriptor.Unknown.Id)) != 0)) {\r
194 return EFI_UNSUPPORTED;\r
195 }\r
196\r
197 //\r
198 // Look for "TEA01" identifier in the Extended Area\r
199 //\r
200 Offset += UDF_LOGICAL_SECTOR_SIZE;\r
201 if (Offset >= EndDiskOffset) {\r
202 return EFI_UNSUPPORTED;\r
203 }\r
204\r
205 Status = DiskIo->ReadDisk (\r
206 DiskIo,\r
207 BlockIo->Media->MediaId,\r
208 Offset,\r
209 sizeof (CDROM_VOLUME_DESCRIPTOR),\r
210 (VOID *)&VolDescriptor\r
211 );\r
212 if (EFI_ERROR (Status)) {\r
213 return Status;\r
214 }\r
215\r
216 if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,\r
217 (VOID *)UDF_TEA_IDENTIFIER,\r
218 sizeof (VolDescriptor.Unknown.Id)) != 0) {\r
219 return EFI_UNSUPPORTED;\r
220 }\r
221\r
222 Status = FindAnchorVolumeDescriptorPointer (BlockIo, DiskIo, &AnchorPoint);\r
223 if (EFI_ERROR (Status)) {\r
224 return EFI_UNSUPPORTED;\r
225 }\r
226\r
227 return EFI_SUCCESS;\r
228}\r
229\r
230/**\r
231 Install child handles if the Handle supports UDF/ECMA-167 volume format.\r
232\r
233 @param[in] This Calling context.\r
234 @param[in] Handle Parent Handle.\r
235 @param[in] DiskIo Parent DiskIo interface.\r
236 @param[in] DiskIo2 Parent DiskIo2 interface.\r
237 @param[in] BlockIo Parent BlockIo interface.\r
238 @param[in] BlockIo2 Parent BlockIo2 interface.\r
239 @param[in] DevicePath Parent Device Path\r
240\r
241\r
242 @retval EFI_SUCCESS Child handle(s) was added.\r
243 @retval EFI_MEDIA_CHANGED Media changed Detected.\r
244 @retval other no child handle was added.\r
245\r
246**/\r
247EFI_STATUS\r
248PartitionInstallUdfChildHandles (\r
249 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
250 IN EFI_HANDLE Handle,\r
251 IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
252 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,\r
253 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
254 IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,\r
255 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
256 )\r
257{\r
b19aeeb9 258 UINT32 RemainderByMediaBlockSize;\r
8aafec2c
PA
259 EFI_STATUS Status;\r
260 EFI_BLOCK_IO_MEDIA *Media;\r
261 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
262 EFI_GUID *VendorDefinedGuid;\r
263 EFI_GUID UdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;\r
264 EFI_PARTITION_INFO_PROTOCOL PartitionInfo;\r
265\r
266 Media = BlockIo->Media;\r
267\r
268 //\r
269 // Check if UDF logical block size is multiple of underlying device block size\r
270 //\r
b19aeeb9
LE
271 DivU64x32Remainder (\r
272 UDF_LOGICAL_SECTOR_SIZE, // Dividend\r
273 Media->BlockSize, // Divisor\r
274 &RemainderByMediaBlockSize // Remainder\r
275 );\r
b4e5807d 276 if (RemainderByMediaBlockSize != 0) {\r
8aafec2c
PA
277 return EFI_NOT_FOUND;\r
278 }\r
279\r
280 DevicePathNode = DevicePath;\r
281 while (!IsDevicePathEnd (DevicePathNode)) {\r
282 //\r
283 // Do not allow checking for UDF file systems in CDROM "El Torito"\r
284 // partitions, and skip duplicate installation of UDF file system child\r
285 // nodes.\r
286 //\r
287 if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) {\r
288 if (DevicePathSubType (DevicePathNode) == MEDIA_CDROM_DP) {\r
289 return EFI_NOT_FOUND;\r
290 }\r
291 if (DevicePathSubType (DevicePathNode) == MEDIA_VENDOR_DP) {\r
292 VendorDefinedGuid = (EFI_GUID *)((UINTN)DevicePathNode +\r
293 OFFSET_OF (VENDOR_DEVICE_PATH, Guid));\r
294 if (CompareGuid (VendorDefinedGuid, &UdfDevPathGuid)) {\r
295 return EFI_NOT_FOUND;\r
296 }\r
297 }\r
298 }\r
299 //\r
300 // Try next device path node\r
301 //\r
302 DevicePathNode = NextDevicePathNode (DevicePathNode);\r
303 }\r
304\r
305 //\r
306 // Check if block device supports an UDF file system\r
307 //\r
308 Status = SupportUdfFileSystem (BlockIo, DiskIo);\r
309 if (EFI_ERROR (Status)) {\r
310 return EFI_NOT_FOUND;\r
311 }\r
312\r
313 //\r
314 // Create Partition Info protocol for UDF file system\r
315 //\r
316 ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));\r
317 PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;\r
318 PartitionInfo.Type = PARTITION_TYPE_OTHER;\r
319\r
320 //\r
321 // Install partition child handle for UDF file system\r
322 //\r
323 Status = PartitionInstallChildHandle (\r
324 This,\r
325 Handle,\r
326 DiskIo,\r
327 DiskIo2,\r
328 BlockIo,\r
329 BlockIo2,\r
330 DevicePath,\r
331 (EFI_DEVICE_PATH_PROTOCOL *)&gUdfDevicePath,\r
332 &PartitionInfo,\r
333 0,\r
334 Media->LastBlock,\r
335 Media->BlockSize\r
336 );\r
337 if (!EFI_ERROR (Status)) {\r
338 Status = EFI_NOT_FOUND;\r
339 }\r
340\r
341 return Status;\r
342}\r