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