Coverage Report

Created: 2025-10-21 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/edk2/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
Line
Count
Source
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
0
#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
0
{
77
0
  EFI_STATUS                            Status;
78
0
  UINT32                                BlockSize;
79
0
  EFI_LBA                               EndLBA;
80
0
  UDF_DESCRIPTOR_TAG                    *DescriptorTag;
81
0
  UINTN                                 AvdpsCount;
82
0
  UINTN                                 Size;
83
0
  UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER  *AnchorPoints;
84
0
  INTN                                  Index;
85
0
  UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER  *AnchorPointPtr;
86
0
  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
0
  BlockSize          = BlockIo->Media->BlockSize;
105
0
  EndLBA             = BlockIo->Media->LastBlock;
106
0
  *LastRecordedBlock = EndLBA;
107
0
  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
0
  if (BlockSize < sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER)) {
114
0
    DEBUG ((
115
0
      DEBUG_ERROR,
116
0
      "%a: Media block size 0x%x unable to hold an AVDP.\n",
117
0
      __func__,
118
0
      BlockSize
119
0
      ));
120
0
    return EFI_UNSUPPORTED;
121
0
  }
122
123
  //
124
  // Find AVDP at block 256
125
  //
126
0
  Status = DiskIo->ReadDisk (
127
0
                     DiskIo,
128
0
                     BlockIo->Media->MediaId,
129
0
                     MultU64x32 (256, BlockSize),
130
0
                     sizeof (*AnchorPoint),
131
0
                     AnchorPoint
132
0
                     );
133
0
  if (EFI_ERROR (Status)) {
134
0
    return Status;
135
0
  }
136
137
0
  DescriptorTag = &AnchorPoint->DescriptorTag;
138
139
  //
140
  // Check if read block is a valid AVDP descriptor
141
  //
142
0
  if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
143
0
    DEBUG ((DEBUG_INFO, "%a: found AVDP at block %d\n", __func__, 256));
144
0
    AvdpsCount++;
145
0
  }
146
147
  //
148
  // Find AVDP at block N - 256
149
  //
150
0
  Status = DiskIo->ReadDisk (
151
0
                     DiskIo,
152
0
                     BlockIo->Media->MediaId,
153
0
                     MultU64x32 ((UINT64)EndLBA - 256, BlockSize),
154
0
                     sizeof (*AnchorPoint),
155
0
                     AnchorPoint
156
0
                     );
157
0
  if (EFI_ERROR (Status)) {
158
0
    return Status;
159
0
  }
160
161
  //
162
  // Check if read block is a valid AVDP descriptor
163
  //
164
0
  if ((DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) &&
165
0
      (++AvdpsCount == 2))
166
0
  {
167
0
    DEBUG ((
168
0
      DEBUG_INFO,
169
0
      "%a: found AVDP at block %Ld\n",
170
0
      __func__,
171
0
      EndLBA - 256
172
0
      ));
173
0
    return EFI_SUCCESS;
174
0
  }
175
176
  //
177
  // Check if at least one AVDP was found in previous locations
178
  //
179
0
  if (AvdpsCount == 0) {
180
0
    return EFI_VOLUME_CORRUPTED;
181
0
  }
182
183
  //
184
  // Find AVDP at block N
185
  //
186
0
  Status = DiskIo->ReadDisk (
187
0
                     DiskIo,
188
0
                     BlockIo->Media->MediaId,
189
0
                     MultU64x32 ((UINT64)EndLBA, BlockSize),
190
0
                     sizeof (*AnchorPoint),
191
0
                     AnchorPoint
192
0
                     );
193
0
  if (EFI_ERROR (Status)) {
194
0
    return Status;
195
0
  }
196
197
  //
198
  // Check if read block is a valid AVDP descriptor
199
  //
200
0
  if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
201
0
    return EFI_SUCCESS;
202
0
  }
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
0
  Size = MAX_CORRECTION_BLOCKS_NUM * BlockSize;
213
214
0
  AnchorPoints = AllocateZeroPool (Size);
215
0
  if (AnchorPoints == NULL) {
216
0
    return EFI_OUT_OF_RESOURCES;
217
0
  }
218
219
  //
220
  // Read consecutive MAX_CORRECTION_BLOCKS_NUM disk blocks
221
  //
222
0
  Status = DiskIo->ReadDisk (
223
0
                     DiskIo,
224
0
                     BlockIo->Media->MediaId,
225
0
                     MultU64x32 ((UINT64)EndLBA - MAX_CORRECTION_BLOCKS_NUM, BlockSize),
226
0
                     Size,
227
0
                     AnchorPoints
228
0
                     );
229
0
  if (EFI_ERROR (Status)) {
230
0
    goto Out_Free;
231
0
  }
232
233
0
  Status = EFI_VOLUME_CORRUPTED;
234
235
  //
236
  // Search for AVDP from blocks N-1 through N-MAX_CORRECTION_BLOCKS_NUM
237
  //
238
0
  for (Index = MAX_CORRECTION_BLOCKS_NUM - 2; Index >= 0; Index--) {
239
0
    AnchorPointPtr = (VOID *)((UINTN)AnchorPoints + Index * BlockSize);
240
241
0
    DescriptorTag = &AnchorPointPtr->DescriptorTag;
242
243
    //
244
    // Check if read block is a valid AVDP descriptor
245
    //
246
0
    if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
247
      //
248
      // Calculate last recorded block number
249
      //
250
0
      LastAvdpBlockNum = EndLBA - (MAX_CORRECTION_BLOCKS_NUM - Index);
251
0
      DEBUG ((
252
0
        DEBUG_WARN,
253
0
        "%a: found AVDP at block %Ld\n",
254
0
        __func__,
255
0
        LastAvdpBlockNum
256
0
        ));
257
0
      DEBUG ((
258
0
        DEBUG_WARN,
259
0
        "%a: correcting last block from %Ld to %Ld\n",
260
0
        __func__,
261
0
        EndLBA,
262
0
        LastAvdpBlockNum
263
0
        ));
264
      //
265
      // Save read AVDP from last block
266
      //
267
0
      CopyMem (AnchorPoint, AnchorPointPtr, sizeof (*AnchorPointPtr));
268
      //
269
      // Set last recorded block number
270
      //
271
0
      *LastRecordedBlock = LastAvdpBlockNum;
272
0
      Status             = EFI_SUCCESS;
273
0
      break;
274
0
    }
275
0
  }
276
277
0
Out_Free:
278
0
  FreePool (AnchorPoints);
279
0
  return Status;
280
0
}
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
0
{
299
0
  EFI_STATUS               Status;
300
0
  UINT64                   Offset;
301
0
  UINT64                   EndDiskOffset;
302
0
  CDROM_VOLUME_DESCRIPTOR  VolDescriptor;
303
0
  CDROM_VOLUME_DESCRIPTOR  TerminatingVolDescriptor;
304
305
0
  ZeroMem ((VOID *)&TerminatingVolDescriptor, sizeof (CDROM_VOLUME_DESCRIPTOR));
306
307
  //
308
  // Start Volume Recognition Sequence
309
  //
310
0
  EndDiskOffset = MultU64x32 (
311
0
                    BlockIo->Media->LastBlock,
312
0
                    BlockIo->Media->BlockSize
313
0
                    );
314
315
0
  for (Offset = UDF_VRS_START_OFFSET; Offset < EndDiskOffset;
316
0
       Offset += UDF_LOGICAL_SECTOR_SIZE)
317
0
  {
318
    //
319
    // Check if block device has a Volume Structure Descriptor and an Extended
320
    // Area.
321
    //
322
0
    Status = DiskIo->ReadDisk (
323
0
                       DiskIo,
324
0
                       BlockIo->Media->MediaId,
325
0
                       Offset,
326
0
                       sizeof (CDROM_VOLUME_DESCRIPTOR),
327
0
                       (VOID *)&VolDescriptor
328
0
                       );
329
0
    if (EFI_ERROR (Status)) {
330
0
      return Status;
331
0
    }
332
333
0
    if (CompareMem (
334
0
          (VOID *)VolDescriptor.Unknown.Id,
335
0
          (VOID *)UDF_BEA_IDENTIFIER,
336
0
          sizeof (VolDescriptor.Unknown.Id)
337
0
          ) == 0)
338
0
    {
339
0
      break;
340
0
    }
341
342
0
    if ((CompareMem (
343
0
           (VOID *)VolDescriptor.Unknown.Id,
344
0
           (VOID *)CDVOL_ID,
345
0
           sizeof (VolDescriptor.Unknown.Id)
346
0
           ) != 0) ||
347
0
        (CompareMem (
348
0
           (VOID *)&VolDescriptor,
349
0
           (VOID *)&TerminatingVolDescriptor,
350
0
           sizeof (CDROM_VOLUME_DESCRIPTOR)
351
0
           ) == 0))
352
0
    {
353
0
      return EFI_NOT_FOUND;
354
0
    }
355
0
  }
356
357
  //
358
  // Look for "NSR0{2,3}" identifiers in the Extended Area.
359
  //
360
0
  Offset += UDF_LOGICAL_SECTOR_SIZE;
361
0
  if (Offset >= EndDiskOffset) {
362
0
    return EFI_NOT_FOUND;
363
0
  }
364
365
0
  Status = DiskIo->ReadDisk (
366
0
                     DiskIo,
367
0
                     BlockIo->Media->MediaId,
368
0
                     Offset,
369
0
                     sizeof (CDROM_VOLUME_DESCRIPTOR),
370
0
                     (VOID *)&VolDescriptor
371
0
                     );
372
0
  if (EFI_ERROR (Status)) {
373
0
    return Status;
374
0
  }
375
376
0
  if ((CompareMem (
377
0
         (VOID *)VolDescriptor.Unknown.Id,
378
0
         (VOID *)UDF_NSR2_IDENTIFIER,
379
0
         sizeof (VolDescriptor.Unknown.Id)
380
0
         ) != 0) &&
381
0
      (CompareMem (
382
0
         (VOID *)VolDescriptor.Unknown.Id,
383
0
         (VOID *)UDF_NSR3_IDENTIFIER,
384
0
         sizeof (VolDescriptor.Unknown.Id)
385
0
         ) != 0))
386
0
  {
387
0
    return EFI_NOT_FOUND;
388
0
  }
389
390
  //
391
  // Look for "TEA01" identifier in the Extended Area
392
  //
393
0
  Offset += UDF_LOGICAL_SECTOR_SIZE;
394
0
  if (Offset >= EndDiskOffset) {
395
0
    return EFI_NOT_FOUND;
396
0
  }
397
398
0
  Status = DiskIo->ReadDisk (
399
0
                     DiskIo,
400
0
                     BlockIo->Media->MediaId,
401
0
                     Offset,
402
0
                     sizeof (CDROM_VOLUME_DESCRIPTOR),
403
0
                     (VOID *)&VolDescriptor
404
0
                     );
405
0
  if (EFI_ERROR (Status)) {
406
0
    return Status;
407
0
  }
408
409
0
  if (CompareMem (
410
0
        (VOID *)VolDescriptor.Unknown.Id,
411
0
        (VOID *)UDF_TEA_IDENTIFIER,
412
0
        sizeof (VolDescriptor.Unknown.Id)
413
0
        ) != 0)
414
0
  {
415
0
    return EFI_NOT_FOUND;
416
0
  }
417
418
0
  return EFI_SUCCESS;
419
0
}
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
0
{
436
  //
437
  // Check for a valid UDF revision range
438
  //
439
0
  switch (LogicalVolDesc->DomainIdentifier.Suffix.Domain.UdfRevision) {
440
0
    case 0x0102:
441
0
    case 0x0150:
442
0
    case 0x0200:
443
0
    case 0x0201:
444
0
    case 0x0250:
445
0
    case 0x0260:
446
0
      break;
447
0
    default:
448
0
      return FALSE;
449
0
  }
450
451
  //
452
  // Check for a single Partition Map
453
  //
454
0
  if (LogicalVolDesc->NumberOfPartitionMaps > 1) {
455
0
    return FALSE;
456
0
  }
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
0
  if ((LogicalVolDesc->PartitionMaps[0] != 1) ||
466
0
      (LogicalVolDesc->PartitionMaps[1] != 6))
467
0
  {
468
0
    return FALSE;
469
0
  }
470
471
0
  return TRUE;
472
0
}
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
0
{
501
0
  EFI_STATUS                     Status;
502
0
  UINT32                         BlockSize;
503
0
  UDF_EXTENT_AD                  *ExtentAd;
504
0
  UINT64                         SeqBlocksNum;
505
0
  UINT64                         SeqStartBlock;
506
0
  UINT64                         GuardMainVdsStartBlock;
507
0
  VOID                           *Buffer;
508
0
  UINT64                         SeqEndBlock;
509
0
  BOOLEAN                        StopSequence;
510
0
  UINTN                          LvdsCount;
511
0
  UDF_LOGICAL_VOLUME_DESCRIPTOR  *LogicalVolDesc;
512
0
  UDF_DESCRIPTOR_TAG             *DescriptorTag;
513
514
0
  BlockSize = BlockIo->Media->BlockSize;
515
0
  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
0
  SeqBlocksNum = DivU64x32 ((UINT64)ExtentAd->ExtentLength, BlockSize);
526
0
  if ((SeqBlocksNum < 16) || ((EFI_LBA)SeqBlocksNum > LastRecordedBlock + 1)) {
527
0
    return EFI_VOLUME_CORRUPTED;
528
0
  }
529
530
  //
531
  // Check for valid Volume Descriptor Sequence starting block number
532
  //
533
0
  SeqStartBlock = (UINT64)ExtentAd->ExtentLocation;
534
0
  if ((SeqStartBlock > LastRecordedBlock) ||
535
0
      (SeqStartBlock + SeqBlocksNum - 1 > LastRecordedBlock))
536
0
  {
537
0
    return EFI_VOLUME_CORRUPTED;
538
0
  }
539
540
0
  GuardMainVdsStartBlock = SeqStartBlock;
541
542
  //
543
  // Allocate buffer for reading disk blocks
544
  //
545
0
  Buffer = AllocateZeroPool ((UINTN)BlockSize);
546
0
  if (Buffer == NULL) {
547
0
    return EFI_OUT_OF_RESOURCES;
548
0
  }
549
550
0
  SeqEndBlock  = SeqStartBlock + SeqBlocksNum;
551
0
  StopSequence = FALSE;
552
0
  LvdsCount    = 0;
553
0
  Status       = EFI_VOLUME_CORRUPTED;
554
  //
555
  // Start Main Volume Descriptor Sequence
556
  //
557
0
  for ( ; SeqStartBlock < SeqEndBlock && !StopSequence; SeqStartBlock++) {
558
    //
559
    // Read disk block
560
    //
561
0
    Status = BlockIo->ReadBlocks (
562
0
                        BlockIo,
563
0
                        BlockIo->Media->MediaId,
564
0
                        SeqStartBlock,
565
0
                        BlockSize,
566
0
                        Buffer
567
0
                        );
568
0
    if (EFI_ERROR (Status)) {
569
0
      goto Out_Free;
570
0
    }
571
572
0
    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
0
    switch (DescriptorTag->TagIdentifier) {
589
0
      case UdfPrimaryVolumeDescriptor:
590
0
      case UdfImplemenationUseVolumeDescriptor:
591
0
      case UdfPartitionDescriptor:
592
0
      case UdfUnallocatedSpaceDescriptor:
593
0
        break;
594
595
0
      case UdfLogicalVolumeDescriptor:
596
0
        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
0
        if ((++LvdsCount > 1) ||
603
0
            !IsLogicalVolumeDescriptorSupported (LogicalVolDesc))
604
0
        {
605
0
          Status       = EFI_UNSUPPORTED;
606
0
          StopSequence = TRUE;
607
0
        }
608
609
0
        break;
610
611
0
      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
0
        StopSequence = TRUE;
618
0
        break;
619
620
0
      default:
621
        //
622
        // An invalid Volume Descriptor has been found in the sequece. Volume is
623
        // corrupted.
624
        //
625
0
        Status = EFI_VOLUME_CORRUPTED;
626
0
        goto Out_Free;
627
0
    }
628
0
  }
629
630
  //
631
  // Check if LVD was found
632
  //
633
0
  if (!EFI_ERROR (Status) && (LvdsCount == 1)) {
634
0
    *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
0
    *MainVdsEndBlock = LastRecordedBlock;
641
642
0
    Status = EFI_SUCCESS;
643
0
  }
644
645
0
Out_Free:
646
  //
647
  // Free block read buffer
648
  //
649
0
  FreePool (Buffer);
650
651
0
  return Status;
652
0
}
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
0
{
680
0
  EFI_STATUS                            Status;
681
0
  UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER  AnchorPoint;
682
0
  EFI_LBA                               LastRecordedBlock;
683
684
  //
685
  // Find UDF volume identifiers
686
  //
687
0
  Status = FindUdfVolumeIdentifiers (BlockIo, DiskIo);
688
0
  if (EFI_ERROR (Status)) {
689
0
    return Status;
690
0
  }
691
692
  //
693
  // Find Anchor Volume Descriptor Pointer
694
  //
695
0
  Status = FindAnchorVolumeDescriptorPointer (
696
0
             BlockIo,
697
0
             DiskIo,
698
0
             &AnchorPoint,
699
0
             &LastRecordedBlock
700
0
             );
701
0
  if (EFI_ERROR (Status)) {
702
0
    return Status;
703
0
  }
704
705
  //
706
  // Find Logical Volume location
707
  //
708
0
  Status = FindLogicalVolumeLocation (
709
0
             BlockIo,
710
0
             DiskIo,
711
0
             &AnchorPoint,
712
0
             LastRecordedBlock,
713
0
             (UINT64 *)StartingLBA,
714
0
             (UINT64 *)EndingLBA
715
0
             );
716
717
0
  return Status;
718
0
}
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
0
{
748
0
  UINT32                       RemainderByMediaBlockSize;
749
0
  EFI_STATUS                   Status;
750
0
  EFI_BLOCK_IO_MEDIA           *Media;
751
0
  EFI_PARTITION_INFO_PROTOCOL  PartitionInfo;
752
0
  EFI_LBA                      StartingLBA;
753
0
  EFI_LBA                      EndingLBA;
754
0
  BOOLEAN                      ChildCreated;
755
756
0
  Media        = BlockIo->Media;
757
0
  ChildCreated = FALSE;
758
759
  //
760
  // Check if UDF logical block size is multiple of underlying device block size
761
  //
762
0
  DivU64x32Remainder (
763
0
    UDF_LOGICAL_SECTOR_SIZE,   // Dividend
764
0
    Media->BlockSize,          // Divisor
765
0
    &RemainderByMediaBlockSize // Remainder
766
0
    );
767
0
  if (RemainderByMediaBlockSize != 0) {
768
0
    return EFI_NOT_FOUND;
769
0
  }
770
771
  //
772
  // Detect El Torito feature first.
773
  // And always continue to search for UDF.
774
  //
775
0
  Status = PartitionInstallElToritoChildHandles (
776
0
             This,
777
0
             Handle,
778
0
             DiskIo,
779
0
             DiskIo2,
780
0
             BlockIo,
781
0
             BlockIo2,
782
0
             DevicePath
783
0
             );
784
0
  if (!EFI_ERROR (Status)) {
785
0
    DEBUG ((DEBUG_INFO, "PartitionDxe: El Torito standard found on handle 0x%p.\n", Handle));
786
0
    ChildCreated = TRUE;
787
0
  }
788
789
  //
790
  // Search for an UDF file system on block device
791
  //
792
0
  Status = FindUdfFileSystem (BlockIo, DiskIo, &StartingLBA, &EndingLBA);
793
0
  if (EFI_ERROR (Status)) {
794
0
    return (ChildCreated ? EFI_SUCCESS : EFI_NOT_FOUND);
795
0
  }
796
797
  //
798
  // Create Partition Info protocol for UDF file system
799
  //
800
0
  ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
801
0
  PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
802
0
  PartitionInfo.Type     = PARTITION_TYPE_OTHER;
803
804
  //
805
  // Install partition child handle for UDF file system
806
  //
807
0
  Status = PartitionInstallChildHandle (
808
0
             This,
809
0
             Handle,
810
0
             DiskIo,
811
0
             DiskIo2,
812
0
             BlockIo,
813
0
             BlockIo2,
814
0
             DevicePath,
815
0
             (EFI_DEVICE_PATH_PROTOCOL *)&gUdfDevicePath,
816
0
             &PartitionInfo,
817
0
             StartingLBA,
818
0
             EndingLBA,
819
0
             Media->BlockSize,
820
0
             NULL
821
0
             );
822
0
  if (EFI_ERROR (Status)) {
823
0
    return (ChildCreated ? EFI_SUCCESS : Status);
824
0
  }
825
826
0
  return EFI_SUCCESS;
827
0
}