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