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