2 Scan for an UDF file system on a formatted media.
4 Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
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
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.
15 #include "Partition.h"
18 // C5BD4D42-1A76-4996-8956-73CDA326CD0A
20 #define EFI_UDF_DEVICE_PATH_GUID \
21 { 0xC5BD4D42, 0x1A76, 0x4996, \
22 { 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A } \
26 VENDOR_DEVICE_PATH DevicePath
;
27 EFI_DEVICE_PATH_PROTOCOL End
;
31 // Vendor-Defined Media Device Path for UDF file system
33 UDF_DEVICE_PATH gUdfDevicePath
= {
34 { { MEDIA_DEVICE_PATH
, MEDIA_VENDOR_DP
,
35 { sizeof (VENDOR_DEVICE_PATH
), 0 } },
36 EFI_UDF_DEVICE_PATH_GUID
38 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
39 { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0 }
44 Find the anchor volume descriptor pointer.
46 @param[in] BlockIo BlockIo interface.
47 @param[in] DiskIo DiskIo interface.
48 @param[out] AnchorPoint Anchor volume descriptor pointer.
50 @retval EFI_SUCCESS Anchor volume descriptor pointer found.
51 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
52 @retval other Anchor volume descriptor pointer not found.
56 FindAnchorVolumeDescriptorPointer (
57 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
58 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
59 OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
*AnchorPoint
65 EFI_LBA DescriptorLBAs
[4];
68 BlockSize
= BlockIo
->Media
->BlockSize
;
69 EndLBA
= BlockIo
->Media
->LastBlock
;
70 DescriptorLBAs
[0] = 256;
71 DescriptorLBAs
[1] = EndLBA
- 256;
72 DescriptorLBAs
[2] = EndLBA
;
73 DescriptorLBAs
[3] = 512;
75 for (Index
= 0; Index
< ARRAY_SIZE (DescriptorLBAs
); Index
++) {
76 Status
= DiskIo
->ReadDisk (
78 BlockIo
->Media
->MediaId
,
79 MultU64x32 (DescriptorLBAs
[Index
], BlockSize
),
80 sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
),
83 if (EFI_ERROR (Status
)) {
87 // Check if read LBA has a valid AVDP descriptor.
89 if (IS_AVDP (AnchorPoint
)) {
96 return EFI_VOLUME_CORRUPTED
;
100 Check if block device supports a valid UDF file system as specified by OSTA
101 Universal Disk Format Specification 2.60.
103 @param[in] BlockIo BlockIo interface.
104 @param[in] DiskIo DiskIo interface.
106 @retval EFI_SUCCESS UDF file system found.
107 @retval EFI_UNSUPPORTED UDF file system not found.
108 @retval EFI_NO_MEDIA The device has no media.
109 @retval EFI_DEVICE_ERROR The device reported an error.
110 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
111 @retval EFI_OUT_OF_RESOURCES The scan was not successful due to lack of
116 SupportUdfFileSystem (
117 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
118 IN EFI_DISK_IO_PROTOCOL
*DiskIo
123 UINT64 EndDiskOffset
;
124 CDROM_VOLUME_DESCRIPTOR VolDescriptor
;
125 CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor
;
126 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint
;
128 ZeroMem ((VOID
*)&TerminatingVolDescriptor
, sizeof (CDROM_VOLUME_DESCRIPTOR
));
131 // Start Volume Recognition Sequence
133 EndDiskOffset
= MultU64x32 (BlockIo
->Media
->LastBlock
,
134 BlockIo
->Media
->BlockSize
);
136 for (Offset
= UDF_VRS_START_OFFSET
; Offset
< EndDiskOffset
;
137 Offset
+= UDF_LOGICAL_SECTOR_SIZE
) {
139 // Check if block device has a Volume Structure Descriptor and an Extended
142 Status
= DiskIo
->ReadDisk (
144 BlockIo
->Media
->MediaId
,
146 sizeof (CDROM_VOLUME_DESCRIPTOR
),
147 (VOID
*)&VolDescriptor
149 if (EFI_ERROR (Status
)) {
153 if (CompareMem ((VOID
*)VolDescriptor
.Unknown
.Id
,
154 (VOID
*)UDF_BEA_IDENTIFIER
,
155 sizeof (VolDescriptor
.Unknown
.Id
)) == 0) {
159 if ((CompareMem ((VOID
*)VolDescriptor
.Unknown
.Id
,
161 sizeof (VolDescriptor
.Unknown
.Id
)) != 0) ||
162 (CompareMem ((VOID
*)&VolDescriptor
,
163 (VOID
*)&TerminatingVolDescriptor
,
164 sizeof (CDROM_VOLUME_DESCRIPTOR
)) == 0)) {
165 return EFI_UNSUPPORTED
;
170 // Look for "NSR0{2,3}" identifiers in the Extended Area.
172 Offset
+= UDF_LOGICAL_SECTOR_SIZE
;
173 if (Offset
>= EndDiskOffset
) {
174 return EFI_UNSUPPORTED
;
177 Status
= DiskIo
->ReadDisk (
179 BlockIo
->Media
->MediaId
,
181 sizeof (CDROM_VOLUME_DESCRIPTOR
),
182 (VOID
*)&VolDescriptor
184 if (EFI_ERROR (Status
)) {
188 if ((CompareMem ((VOID
*)VolDescriptor
.Unknown
.Id
,
189 (VOID
*)UDF_NSR2_IDENTIFIER
,
190 sizeof (VolDescriptor
.Unknown
.Id
)) != 0) &&
191 (CompareMem ((VOID
*)VolDescriptor
.Unknown
.Id
,
192 (VOID
*)UDF_NSR3_IDENTIFIER
,
193 sizeof (VolDescriptor
.Unknown
.Id
)) != 0)) {
194 return EFI_UNSUPPORTED
;
198 // Look for "TEA01" identifier in the Extended Area
200 Offset
+= UDF_LOGICAL_SECTOR_SIZE
;
201 if (Offset
>= EndDiskOffset
) {
202 return EFI_UNSUPPORTED
;
205 Status
= DiskIo
->ReadDisk (
207 BlockIo
->Media
->MediaId
,
209 sizeof (CDROM_VOLUME_DESCRIPTOR
),
210 (VOID
*)&VolDescriptor
212 if (EFI_ERROR (Status
)) {
216 if (CompareMem ((VOID
*)VolDescriptor
.Unknown
.Id
,
217 (VOID
*)UDF_TEA_IDENTIFIER
,
218 sizeof (VolDescriptor
.Unknown
.Id
)) != 0) {
219 return EFI_UNSUPPORTED
;
222 Status
= FindAnchorVolumeDescriptorPointer (BlockIo
, DiskIo
, &AnchorPoint
);
223 if (EFI_ERROR (Status
)) {
224 return EFI_UNSUPPORTED
;
231 Install child handles if the Handle supports UDF/ECMA-167 volume format.
233 @param[in] This Calling context.
234 @param[in] Handle Parent Handle.
235 @param[in] DiskIo Parent DiskIo interface.
236 @param[in] DiskIo2 Parent DiskIo2 interface.
237 @param[in] BlockIo Parent BlockIo interface.
238 @param[in] BlockIo2 Parent BlockIo2 interface.
239 @param[in] DevicePath Parent Device Path
242 @retval EFI_SUCCESS Child handle(s) was added.
243 @retval EFI_MEDIA_CHANGED Media changed Detected.
244 @retval other no child handle was added.
248 PartitionInstallUdfChildHandles (
249 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
250 IN EFI_HANDLE Handle
,
251 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
252 IN EFI_DISK_IO2_PROTOCOL
*DiskIo2
,
253 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
254 IN EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
,
255 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
258 UINT32 RemainderByMediaBlockSize
;
260 EFI_BLOCK_IO_MEDIA
*Media
;
261 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
262 EFI_GUID
*VendorDefinedGuid
;
263 EFI_GUID UdfDevPathGuid
= EFI_UDF_DEVICE_PATH_GUID
;
264 EFI_PARTITION_INFO_PROTOCOL PartitionInfo
;
266 Media
= BlockIo
->Media
;
269 // Check if UDF logical block size is multiple of underlying device block size
272 UDF_LOGICAL_SECTOR_SIZE
, // Dividend
273 Media
->BlockSize
, // Divisor
274 &RemainderByMediaBlockSize
// Remainder
276 if (RemainderByMediaBlockSize
!= 0) {
277 return EFI_NOT_FOUND
;
280 DevicePathNode
= DevicePath
;
281 while (!IsDevicePathEnd (DevicePathNode
)) {
283 // Do not allow checking for UDF file systems in CDROM "El Torito"
284 // partitions, and skip duplicate installation of UDF file system child
287 if (DevicePathType (DevicePathNode
) == MEDIA_DEVICE_PATH
) {
288 if (DevicePathSubType (DevicePathNode
) == MEDIA_CDROM_DP
) {
289 return EFI_NOT_FOUND
;
291 if (DevicePathSubType (DevicePathNode
) == MEDIA_VENDOR_DP
) {
292 VendorDefinedGuid
= (EFI_GUID
*)((UINTN
)DevicePathNode
+
293 OFFSET_OF (VENDOR_DEVICE_PATH
, Guid
));
294 if (CompareGuid (VendorDefinedGuid
, &UdfDevPathGuid
)) {
295 return EFI_NOT_FOUND
;
300 // Try next device path node
302 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
306 // Check if block device supports an UDF file system
308 Status
= SupportUdfFileSystem (BlockIo
, DiskIo
);
309 if (EFI_ERROR (Status
)) {
310 return EFI_NOT_FOUND
;
314 // Create Partition Info protocol for UDF file system
316 ZeroMem (&PartitionInfo
, sizeof (EFI_PARTITION_INFO_PROTOCOL
));
317 PartitionInfo
.Revision
= EFI_PARTITION_INFO_PROTOCOL_REVISION
;
318 PartitionInfo
.Type
= PARTITION_TYPE_OTHER
;
321 // Install partition child handle for UDF file system
323 Status
= PartitionInstallChildHandle (
331 (EFI_DEVICE_PATH_PROTOCOL
*)&gUdfDevicePath
,
337 if (!EFI_ERROR (Status
)) {
338 Status
= EFI_NOT_FOUND
;