]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / PartitionDxe / Udf.c
1 /** @file
2 Scan for an UDF file system on a formatted media.
3
4 Caution: This file requires additional review when modified.
5 This driver will have external input - CD/DVD media.
6 This external input must be validated carefully to avoid security issue like
7 buffer overflow, integer overflow.
8
9 FindUdfFileSystem() routine will consume the media properties and do basic
10 validation.
11
12 Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.
13 Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
14 Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
15
16 SPDX-License-Identifier: BSD-2-Clause-Patent
17 **/
18
19 #include "Partition.h"
20
21 #define MAX_CORRECTION_BLOCKS_NUM 512u
22
23 //
24 // C5BD4D42-1A76-4996-8956-73CDA326CD0A
25 //
26 #define EFI_UDF_DEVICE_PATH_GUID \
27 { 0xC5BD4D42, 0x1A76, 0x4996, \
28 { 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A } \
29 }
30
31 typedef struct {
32 VENDOR_DEVICE_PATH DevicePath;
33 EFI_DEVICE_PATH_PROTOCOL End;
34 } UDF_DEVICE_PATH;
35
36 //
37 // Vendor-Defined Device Path GUID for UDF file system
38 //
39 EFI_GUID gUdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;
40
41 //
42 // Vendor-Defined Media Device Path for UDF file system
43 //
44 UDF_DEVICE_PATH gUdfDevicePath = {
45 { { MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,
46 { sizeof (VENDOR_DEVICE_PATH), 0 } },
47 EFI_UDF_DEVICE_PATH_GUID
48 },
49 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
50 { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
51 }
52 };
53
54 /**
55 Find the anchor volume descriptor pointer.
56
57 @param[in] BlockIo BlockIo interface.
58 @param[in] DiskIo DiskIo interface.
59 @param[out] AnchorPoint Anchor volume descriptor pointer.
60 @param[out] LastRecordedBlock Last recorded block.
61
62 @retval EFI_SUCCESS Anchor volume descriptor pointer found.
63 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
64 @retval other Anchor volume descriptor pointer not found.
65
66 **/
67 EFI_STATUS
68 FindAnchorVolumeDescriptorPointer (
69 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
70 IN EFI_DISK_IO_PROTOCOL *DiskIo,
71 OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint,
72 OUT EFI_LBA *LastRecordedBlock
73 )
74 {
75 EFI_STATUS Status;
76 UINT32 BlockSize;
77 EFI_LBA EndLBA;
78 UDF_DESCRIPTOR_TAG *DescriptorTag;
79 UINTN AvdpsCount;
80 UINTN Size;
81 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoints;
82 INTN Index;
83 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPointPtr;
84 EFI_LBA LastAvdpBlockNum;
85
86 //
87 // UDF 2.60, 2.2.3 Anchor Volume Descriptor Pointer
88 //
89 // An Anchor Volume Descriptor Pointer structure shall be recorded in at
90 // least 2 of the following 3 locations on the media: Logical Sector 256,
91 // N - 256 or N, where N is the last *addressable* sector of a volume.
92 //
93 // To figure out what logical sector N is, the SCSI commands READ CAPACITY and
94 // READ TRACK INFORMATION are used, however many drives or medias report their
95 // "last recorded block" wrongly. Although, READ CAPACITY returns the last
96 // readable data block but there might be unwritten blocks, which are located
97 // outside any track and therefore AVDP will not be found at block N.
98 //
99 // That said, we define a magic number of 512 blocks to be used as correction
100 // when attempting to find AVDP and define last block number.
101 //
102 BlockSize = BlockIo->Media->BlockSize;
103 EndLBA = BlockIo->Media->LastBlock;
104 *LastRecordedBlock = EndLBA;
105 AvdpsCount = 0;
106
107 //
108 // Check if the block size of the underlying media can hold the data of an
109 // Anchor Volume Descriptor Pointer
110 //
111 if (BlockSize < sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER)) {
112 DEBUG ((
113 DEBUG_ERROR,
114 "%a: Media block size 0x%x unable to hold an AVDP.\n",
115 __FUNCTION__,
116 BlockSize
117 ));
118 return EFI_UNSUPPORTED;
119 }
120
121 //
122 // Find AVDP at block 256
123 //
124 Status = DiskIo->ReadDisk (
125 DiskIo,
126 BlockIo->Media->MediaId,
127 MultU64x32 (256, BlockSize),
128 sizeof (*AnchorPoint),
129 AnchorPoint
130 );
131 if (EFI_ERROR (Status)) {
132 return Status;
133 }
134
135 DescriptorTag = &AnchorPoint->DescriptorTag;
136
137 //
138 // Check if read block is a valid AVDP descriptor
139 //
140 if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
141 DEBUG ((DEBUG_INFO, "%a: found AVDP at block %d\n", __FUNCTION__, 256));
142 AvdpsCount++;
143 }
144
145 //
146 // Find AVDP at block N - 256
147 //
148 Status = DiskIo->ReadDisk (
149 DiskIo,
150 BlockIo->Media->MediaId,
151 MultU64x32 ((UINT64)EndLBA - 256, BlockSize),
152 sizeof (*AnchorPoint),
153 AnchorPoint
154 );
155 if (EFI_ERROR (Status)) {
156 return Status;
157 }
158
159 //
160 // Check if read block is a valid AVDP descriptor
161 //
162 if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer &&
163 ++AvdpsCount == 2) {
164 DEBUG ((DEBUG_INFO, "%a: found AVDP at block %Ld\n", __FUNCTION__,
165 EndLBA - 256));
166 return EFI_SUCCESS;
167 }
168
169 //
170 // Check if at least one AVDP was found in previous locations
171 //
172 if (AvdpsCount == 0) {
173 return EFI_VOLUME_CORRUPTED;
174 }
175
176 //
177 // Find AVDP at block N
178 //
179 Status = DiskIo->ReadDisk (
180 DiskIo,
181 BlockIo->Media->MediaId,
182 MultU64x32 ((UINT64)EndLBA, BlockSize),
183 sizeof (*AnchorPoint),
184 AnchorPoint
185 );
186 if (EFI_ERROR (Status)) {
187 return Status;
188 }
189
190 //
191 // Check if read block is a valid AVDP descriptor
192 //
193 if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
194 return EFI_SUCCESS;
195 }
196
197 //
198 // No AVDP found at block N. Possibly drive/media returned bad last recorded
199 // block, or it is part of unwritten data blocks and outside any track.
200 //
201 // Search backwards for an AVDP from block N-1 through
202 // N-MAX_CORRECTION_BLOCKS_NUM. If any AVDP is found, then correct last block
203 // number for the new UDF partition child handle.
204 //
205 Size = MAX_CORRECTION_BLOCKS_NUM * BlockSize;
206
207 AnchorPoints = AllocateZeroPool (Size);
208 if (AnchorPoints == NULL) {
209 return EFI_OUT_OF_RESOURCES;
210 }
211
212 //
213 // Read consecutive MAX_CORRECTION_BLOCKS_NUM disk blocks
214 //
215 Status = DiskIo->ReadDisk (
216 DiskIo,
217 BlockIo->Media->MediaId,
218 MultU64x32 ((UINT64)EndLBA - MAX_CORRECTION_BLOCKS_NUM, BlockSize),
219 Size,
220 AnchorPoints
221 );
222 if (EFI_ERROR (Status)) {
223 goto Out_Free;
224 }
225
226 Status = EFI_VOLUME_CORRUPTED;
227
228 //
229 // Search for AVDP from blocks N-1 through N-MAX_CORRECTION_BLOCKS_NUM
230 //
231 for (Index = MAX_CORRECTION_BLOCKS_NUM - 2; Index >= 0; Index--) {
232 AnchorPointPtr = (VOID *)((UINTN)AnchorPoints + Index * BlockSize);
233
234 DescriptorTag = &AnchorPointPtr->DescriptorTag;
235
236 //
237 // Check if read block is a valid AVDP descriptor
238 //
239 if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
240 //
241 // Calculate last recorded block number
242 //
243 LastAvdpBlockNum = EndLBA - (MAX_CORRECTION_BLOCKS_NUM - Index);
244 DEBUG ((DEBUG_WARN, "%a: found AVDP at block %Ld\n", __FUNCTION__,
245 LastAvdpBlockNum));
246 DEBUG ((DEBUG_WARN, "%a: correcting last block from %Ld to %Ld\n",
247 __FUNCTION__, EndLBA, LastAvdpBlockNum));
248 //
249 // Save read AVDP from last block
250 //
251 CopyMem (AnchorPoint, AnchorPointPtr, sizeof (*AnchorPointPtr));
252 //
253 // Set last recorded block number
254 //
255 *LastRecordedBlock = LastAvdpBlockNum;
256 Status = EFI_SUCCESS;
257 break;
258 }
259 }
260
261 Out_Free:
262 FreePool (AnchorPoints);
263 return Status;
264 }
265
266 /**
267 Find UDF volume identifiers in a Volume Recognition Sequence.
268
269 @param[in] BlockIo BlockIo interface.
270 @param[in] DiskIo DiskIo interface.
271
272 @retval EFI_SUCCESS UDF volume identifiers were found.
273 @retval EFI_NOT_FOUND UDF volume identifiers were not found.
274 @retval other Failed to perform disk I/O.
275
276 **/
277 EFI_STATUS
278 FindUdfVolumeIdentifiers (
279 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
280 IN EFI_DISK_IO_PROTOCOL *DiskIo
281 )
282 {
283 EFI_STATUS Status;
284 UINT64 Offset;
285 UINT64 EndDiskOffset;
286 CDROM_VOLUME_DESCRIPTOR VolDescriptor;
287 CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor;
288
289 ZeroMem ((VOID *)&TerminatingVolDescriptor, sizeof (CDROM_VOLUME_DESCRIPTOR));
290
291 //
292 // Start Volume Recognition Sequence
293 //
294 EndDiskOffset = MultU64x32 (BlockIo->Media->LastBlock,
295 BlockIo->Media->BlockSize);
296
297 for (Offset = UDF_VRS_START_OFFSET; Offset < EndDiskOffset;
298 Offset += UDF_LOGICAL_SECTOR_SIZE) {
299 //
300 // Check if block device has a Volume Structure Descriptor and an Extended
301 // Area.
302 //
303 Status = DiskIo->ReadDisk (
304 DiskIo,
305 BlockIo->Media->MediaId,
306 Offset,
307 sizeof (CDROM_VOLUME_DESCRIPTOR),
308 (VOID *)&VolDescriptor
309 );
310 if (EFI_ERROR (Status)) {
311 return Status;
312 }
313
314 if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
315 (VOID *)UDF_BEA_IDENTIFIER,
316 sizeof (VolDescriptor.Unknown.Id)) == 0) {
317 break;
318 }
319
320 if ((CompareMem ((VOID *)VolDescriptor.Unknown.Id,
321 (VOID *)CDVOL_ID,
322 sizeof (VolDescriptor.Unknown.Id)) != 0) ||
323 (CompareMem ((VOID *)&VolDescriptor,
324 (VOID *)&TerminatingVolDescriptor,
325 sizeof (CDROM_VOLUME_DESCRIPTOR)) == 0)) {
326 return EFI_NOT_FOUND;
327 }
328 }
329
330 //
331 // Look for "NSR0{2,3}" identifiers in the Extended Area.
332 //
333 Offset += UDF_LOGICAL_SECTOR_SIZE;
334 if (Offset >= EndDiskOffset) {
335 return EFI_NOT_FOUND;
336 }
337
338 Status = DiskIo->ReadDisk (
339 DiskIo,
340 BlockIo->Media->MediaId,
341 Offset,
342 sizeof (CDROM_VOLUME_DESCRIPTOR),
343 (VOID *)&VolDescriptor
344 );
345 if (EFI_ERROR (Status)) {
346 return Status;
347 }
348
349 if ((CompareMem ((VOID *)VolDescriptor.Unknown.Id,
350 (VOID *)UDF_NSR2_IDENTIFIER,
351 sizeof (VolDescriptor.Unknown.Id)) != 0) &&
352 (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
353 (VOID *)UDF_NSR3_IDENTIFIER,
354 sizeof (VolDescriptor.Unknown.Id)) != 0)) {
355 return EFI_NOT_FOUND;
356 }
357
358 //
359 // Look for "TEA01" identifier in the Extended Area
360 //
361 Offset += UDF_LOGICAL_SECTOR_SIZE;
362 if (Offset >= EndDiskOffset) {
363 return EFI_NOT_FOUND;
364 }
365
366 Status = DiskIo->ReadDisk (
367 DiskIo,
368 BlockIo->Media->MediaId,
369 Offset,
370 sizeof (CDROM_VOLUME_DESCRIPTOR),
371 (VOID *)&VolDescriptor
372 );
373 if (EFI_ERROR (Status)) {
374 return Status;
375 }
376
377 if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
378 (VOID *)UDF_TEA_IDENTIFIER,
379 sizeof (VolDescriptor.Unknown.Id)) != 0) {
380 return EFI_NOT_FOUND;
381 }
382
383 return EFI_SUCCESS;
384 }
385
386 /**
387 Check if Logical Volume Descriptor is supported by current EDK2 UDF file
388 system implementation.
389
390 @param[in] LogicalVolDesc Logical Volume Descriptor pointer.
391
392 @retval TRUE Logical Volume Descriptor is supported.
393 @retval FALSE Logical Volume Descriptor is not supported.
394
395 **/
396 BOOLEAN
397 IsLogicalVolumeDescriptorSupported (
398 UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc
399 )
400 {
401 //
402 // Check for a valid UDF revision range
403 //
404 switch (LogicalVolDesc->DomainIdentifier.Suffix.Domain.UdfRevision) {
405 case 0x0102:
406 case 0x0150:
407 case 0x0200:
408 case 0x0201:
409 case 0x0250:
410 case 0x0260:
411 break;
412 default:
413 return FALSE;
414 }
415
416 //
417 // Check for a single Partition Map
418 //
419 if (LogicalVolDesc->NumberOfPartitionMaps > 1) {
420 return FALSE;
421 }
422 //
423 // UDF 1.02 revision supports only Type 1 (Physical) partitions, but
424 // let's check it any way.
425 //
426 // PartitionMap[0] -> type
427 // PartitionMap[1] -> length (in bytes)
428 //
429 if (LogicalVolDesc->PartitionMaps[0] != 1 ||
430 LogicalVolDesc->PartitionMaps[1] != 6) {
431 return FALSE;
432 }
433
434 return TRUE;
435 }
436
437 /**
438 Find UDF logical volume location and whether it is supported by current EDK2
439 UDF file system implementation.
440
441 @param[in] BlockIo BlockIo interface.
442 @param[in] DiskIo DiskIo interface.
443 @param[in] AnchorPoint Anchor volume descriptor pointer.
444 @param[in] LastRecordedBlock Last recorded block in media.
445 @param[out] MainVdsStartBlock Main VDS starting block number.
446 @param[out] MainVdsEndBlock Main VDS ending block number.
447
448 @retval EFI_SUCCESS UDF logical volume was found.
449 @retval EFI_VOLUME_CORRUPTED UDF file system structures are corrupted.
450 @retval EFI_UNSUPPORTED UDF logical volume is not supported.
451 @retval other Failed to perform disk I/O.
452
453 **/
454 EFI_STATUS
455 FindLogicalVolumeLocation (
456 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
457 IN EFI_DISK_IO_PROTOCOL *DiskIo,
458 IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint,
459 IN EFI_LBA LastRecordedBlock,
460 OUT UINT64 *MainVdsStartBlock,
461 OUT UINT64 *MainVdsEndBlock
462 )
463 {
464 EFI_STATUS Status;
465 UINT32 BlockSize;
466 UDF_EXTENT_AD *ExtentAd;
467 UINT64 SeqBlocksNum;
468 UINT64 SeqStartBlock;
469 UINT64 GuardMainVdsStartBlock;
470 VOID *Buffer;
471 UINT64 SeqEndBlock;
472 BOOLEAN StopSequence;
473 UINTN LvdsCount;
474 UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
475 UDF_DESCRIPTOR_TAG *DescriptorTag;
476
477 BlockSize = BlockIo->Media->BlockSize;
478 ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;
479
480 //
481 // UDF 2.60, 2.2.3.1 struct MainVolumeDescriptorSequenceExtent
482 //
483 // The Main Volume Descriptor Sequence Extent shall have a minimum length of
484 // 16 logical sectors.
485 //
486 // Also make sure it does not exceed maximum number of blocks in the disk.
487 //
488 SeqBlocksNum = DivU64x32 ((UINT64)ExtentAd->ExtentLength, BlockSize);
489 if (SeqBlocksNum < 16 || (EFI_LBA)SeqBlocksNum > LastRecordedBlock + 1) {
490 return EFI_VOLUME_CORRUPTED;
491 }
492
493 //
494 // Check for valid Volume Descriptor Sequence starting block number
495 //
496 SeqStartBlock = (UINT64)ExtentAd->ExtentLocation;
497 if (SeqStartBlock > LastRecordedBlock ||
498 SeqStartBlock + SeqBlocksNum - 1 > LastRecordedBlock) {
499 return EFI_VOLUME_CORRUPTED;
500 }
501
502 GuardMainVdsStartBlock = SeqStartBlock;
503
504 //
505 // Allocate buffer for reading disk blocks
506 //
507 Buffer = AllocateZeroPool ((UINTN)BlockSize);
508 if (Buffer == NULL) {
509 return EFI_OUT_OF_RESOURCES;
510 }
511
512 SeqEndBlock = SeqStartBlock + SeqBlocksNum;
513 StopSequence = FALSE;
514 LvdsCount = 0;
515 Status = EFI_VOLUME_CORRUPTED;
516 //
517 // Start Main Volume Descriptor Sequence
518 //
519 for (; SeqStartBlock < SeqEndBlock && !StopSequence; SeqStartBlock++) {
520 //
521 // Read disk block
522 //
523 Status = BlockIo->ReadBlocks (
524 BlockIo,
525 BlockIo->Media->MediaId,
526 SeqStartBlock,
527 BlockSize,
528 Buffer
529 );
530 if (EFI_ERROR (Status)) {
531 goto Out_Free;
532 }
533
534 DescriptorTag = Buffer;
535
536 //
537 // ECMA 167, 8.4.1 Contents of a Volume Descriptor Sequence
538 //
539 // - A Volume Descriptor Sequence shall contain one or more Primary Volume
540 // Descriptors.
541 // - A Volume Descriptor Sequence shall contain zero or more Implementation
542 // Use Volume Descriptors.
543 // - A Volume Descriptor Sequence shall contain zero or more Partition
544 // Descriptors.
545 // - A Volume Descriptor Sequence shall contain zero or more Logical Volume
546 // Descriptors.
547 // - A Volume Descriptor Sequence shall contain zero or more Unallocated
548 // Space Descriptors.
549 //
550 switch (DescriptorTag->TagIdentifier) {
551 case UdfPrimaryVolumeDescriptor:
552 case UdfImplemenationUseVolumeDescriptor:
553 case UdfPartitionDescriptor:
554 case UdfUnallocatedSpaceDescriptor:
555 break;
556
557 case UdfLogicalVolumeDescriptor:
558 LogicalVolDesc = Buffer;
559
560 //
561 // Check for existence of a single LVD and whether it is supported by
562 // current EDK2 UDF file system implementation.
563 //
564 if (++LvdsCount > 1 ||
565 !IsLogicalVolumeDescriptorSupported (LogicalVolDesc)) {
566 Status = EFI_UNSUPPORTED;
567 StopSequence = TRUE;
568 }
569
570 break;
571
572 case UdfTerminatingDescriptor:
573 //
574 // Stop the sequence when we find a Terminating Descriptor
575 // (aka Unallocated Sector), se we don't have to walk all the unallocated
576 // area unnecessarily.
577 //
578 StopSequence = TRUE;
579 break;
580
581 default:
582 //
583 // An invalid Volume Descriptor has been found in the sequece. Volume is
584 // corrupted.
585 //
586 Status = EFI_VOLUME_CORRUPTED;
587 goto Out_Free;
588 }
589 }
590
591 //
592 // Check if LVD was found
593 //
594 if (!EFI_ERROR (Status) && LvdsCount == 1) {
595 *MainVdsStartBlock = GuardMainVdsStartBlock;
596 //
597 // We do not need to read either LVD or PD descriptors to know the last
598 // valid block in the found UDF file system. It's already
599 // LastRecordedBlock.
600 //
601 *MainVdsEndBlock = LastRecordedBlock;
602
603 Status = EFI_SUCCESS;
604 }
605
606 Out_Free:
607 //
608 // Free block read buffer
609 //
610 FreePool (Buffer);
611
612 return Status;
613 }
614
615 /**
616 Find a supported UDF file system in block device.
617
618 @attention This is boundary function that may receive untrusted input.
619 @attention The input is from Partition.
620
621 The CD/DVD media is the external input, so this routine will do basic
622 validation for the media.
623
624 @param[in] BlockIo BlockIo interface.
625 @param[in] DiskIo DiskIo interface.
626 @param[out] StartingLBA UDF file system starting LBA.
627 @param[out] EndingLBA UDF file system starting LBA.
628
629 @retval EFI_SUCCESS UDF file system was found.
630 @retval other UDF file system was not found.
631
632 **/
633 EFI_STATUS
634 FindUdfFileSystem (
635 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
636 IN EFI_DISK_IO_PROTOCOL *DiskIo,
637 OUT EFI_LBA *StartingLBA,
638 OUT EFI_LBA *EndingLBA
639 )
640 {
641 EFI_STATUS Status;
642 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;
643 EFI_LBA LastRecordedBlock;
644
645 //
646 // Find UDF volume identifiers
647 //
648 Status = FindUdfVolumeIdentifiers (BlockIo, DiskIo);
649 if (EFI_ERROR (Status)) {
650 return Status;
651 }
652
653 //
654 // Find Anchor Volume Descriptor Pointer
655 //
656 Status = FindAnchorVolumeDescriptorPointer (
657 BlockIo,
658 DiskIo,
659 &AnchorPoint,
660 &LastRecordedBlock
661 );
662 if (EFI_ERROR (Status)) {
663 return Status;
664 }
665
666 //
667 // Find Logical Volume location
668 //
669 Status = FindLogicalVolumeLocation (
670 BlockIo,
671 DiskIo,
672 &AnchorPoint,
673 LastRecordedBlock,
674 (UINT64 *)StartingLBA,
675 (UINT64 *)EndingLBA
676 );
677
678 return Status;
679 }
680
681 /**
682 Install child handles if the Handle supports UDF/ECMA-167 volume format.
683
684 @param[in] This Calling context.
685 @param[in] Handle Parent Handle.
686 @param[in] DiskIo Parent DiskIo interface.
687 @param[in] DiskIo2 Parent DiskIo2 interface.
688 @param[in] BlockIo Parent BlockIo interface.
689 @param[in] BlockIo2 Parent BlockIo2 interface.
690 @param[in] DevicePath Parent Device Path
691
692
693 @retval EFI_SUCCESS Child handle(s) was added.
694 @retval EFI_MEDIA_CHANGED Media changed Detected.
695 @retval other no child handle was added.
696
697 **/
698 EFI_STATUS
699 PartitionInstallUdfChildHandles (
700 IN EFI_DRIVER_BINDING_PROTOCOL *This,
701 IN EFI_HANDLE Handle,
702 IN EFI_DISK_IO_PROTOCOL *DiskIo,
703 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
704 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
705 IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
706 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
707 )
708 {
709 UINT32 RemainderByMediaBlockSize;
710 EFI_STATUS Status;
711 EFI_BLOCK_IO_MEDIA *Media;
712 EFI_PARTITION_INFO_PROTOCOL PartitionInfo;
713 EFI_LBA StartingLBA;
714 EFI_LBA EndingLBA;
715 BOOLEAN ChildCreated;
716
717 Media = BlockIo->Media;
718 ChildCreated = FALSE;
719
720 //
721 // Check if UDF logical block size is multiple of underlying device block size
722 //
723 DivU64x32Remainder (
724 UDF_LOGICAL_SECTOR_SIZE, // Dividend
725 Media->BlockSize, // Divisor
726 &RemainderByMediaBlockSize // Remainder
727 );
728 if (RemainderByMediaBlockSize != 0) {
729 return EFI_NOT_FOUND;
730 }
731
732 //
733 // Detect El Torito feature first.
734 // And always continue to search for UDF.
735 //
736 Status = PartitionInstallElToritoChildHandles (
737 This,
738 Handle,
739 DiskIo,
740 DiskIo2,
741 BlockIo,
742 BlockIo2,
743 DevicePath
744 );
745 if (!EFI_ERROR (Status)) {
746 DEBUG ((DEBUG_INFO, "PartitionDxe: El Torito standard found on handle 0x%p.\n", Handle));
747 ChildCreated = TRUE;
748 }
749
750 //
751 // Search for an UDF file system on block device
752 //
753 Status = FindUdfFileSystem (BlockIo, DiskIo, &StartingLBA, &EndingLBA);
754 if (EFI_ERROR (Status)) {
755 return (ChildCreated ? EFI_SUCCESS : EFI_NOT_FOUND);
756 }
757
758 //
759 // Create Partition Info protocol for UDF file system
760 //
761 ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
762 PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
763 PartitionInfo.Type = PARTITION_TYPE_OTHER;
764
765 //
766 // Install partition child handle for UDF file system
767 //
768 Status = PartitionInstallChildHandle (
769 This,
770 Handle,
771 DiskIo,
772 DiskIo2,
773 BlockIo,
774 BlockIo2,
775 DevicePath,
776 (EFI_DEVICE_PATH_PROTOCOL *)&gUdfDevicePath,
777 &PartitionInfo,
778 StartingLBA,
779 EndingLBA,
780 Media->BlockSize,
781 NULL
782 );
783 if (EFI_ERROR (Status)) {
784 return (ChildCreated ? EFI_SUCCESS : Status);
785 }
786
787 return EFI_SUCCESS;
788 }