1adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff/** @file
2adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  Decode an El Torito formatted CD-ROM
3adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
4173acde9162ad099005ef25456237c8a0e1b8d7fRuiyu NiCopyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
5e5eed7d3641d71d7ea539e5379ea9c6a5cd97004hhtianThis program and the accompanying materials
6f42be64210ea5ef394835a3c35f0444086537f66qhuangare licensed and made available under the terms and conditions of the BSD License
7f42be64210ea5ef394835a3c35f0444086537f66qhuangwhich accompanies this distribution.  The full text of the license may be found at
8f42be64210ea5ef394835a3c35f0444086537f66qhuanghttp://opensource.org/licenses/bsd-license.php
9f42be64210ea5ef394835a3c35f0444086537f66qhuang
10f42be64210ea5ef394835a3c35f0444086537f66qhuangTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11f42be64210ea5ef394835a3c35f0444086537f66qhuangWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
13adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff**/
14adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
15adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
16adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff#include "Partition.h"
17adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
18adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
19adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff/**
20adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  Install child handles if the Handle supports El Torito format.
21adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
22adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  @param[in]  This        Calling context.
23490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang  @param[in]  Handle      Parent Handle.
24490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang  @param[in]  DiskIo      Parent DiskIo interface.
25493d8e3a5e86f78ef975e18dfa5754adce9e82deRuiyu Ni  @param[in]  DiskIo2     Parent DiskIo2 interface.
26490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang  @param[in]  BlockIo     Parent BlockIo interface.
27490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang  @param[in]  BlockIo2    Parent BlockIo2 interface.
28adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  @param[in]  DevicePath  Parent Device Path
29adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
30adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
31490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang  @retval EFI_SUCCESS         Child handle(s) was added.
32490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang  @retval EFI_MEDIA_CHANGED   Media changed Detected.
33490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang  @retval other               no child handle was added.
34adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
35adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff**/
36adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeffEFI_STATUS
37adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeffPartitionInstallElToritoChildHandles (
38adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
39adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  IN  EFI_HANDLE                   Handle,
40adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
41493d8e3a5e86f78ef975e18dfa5754adce9e82deRuiyu Ni  IN  EFI_DISK_IO2_PROTOCOL        *DiskIo2,
42adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
43490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
44adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
45adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  )
46adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff{
47adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  EFI_STATUS              Status;
485d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  UINT64                  VolDescriptorOffset;
495d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  UINT32                  Lba2KB;
50adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  EFI_BLOCK_IO_MEDIA      *Media;
51adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
52adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  ELTORITO_CATALOG        *Catalog;
53adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  UINTN                   Check;
54adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  UINTN                   Index;
55adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  UINTN                   BootEntry;
56adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  UINTN                   MaxIndex;
57adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  UINT16                  *CheckBuffer;
58adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  CDROM_DEVICE_PATH       CdDev;
59adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  UINT32                  SubBlockSize;
60adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  UINT32                  SectorCount;
61adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  EFI_STATUS              Found;
62adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  UINT32                  VolSpaceSize;
63adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
64adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  Found         = EFI_NOT_FOUND;
65adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  Media         = BlockIo->Media;
66490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang
67adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  VolSpaceSize  = 0;
68adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
69adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  //
705d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  // CD_ROM has the fixed block size as 2048 bytes (SIZE_2KB)
71adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  //
725d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin
735d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  // If the ISO image has been copied onto a different storage media
745d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  // then the block size might be different (eg: USB).
755d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  // Ensure 2048 (SIZE_2KB) is a multiple of block size
765d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  if (((SIZE_2KB % Media->BlockSize) != 0) || (Media->BlockSize > SIZE_2KB)) {
77adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    return EFI_NOT_FOUND;
78adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  }
79adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
805d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  VolDescriptor = AllocatePool ((UINTN)SIZE_2KB);
81adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
82adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  if (VolDescriptor == NULL) {
83adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    return EFI_NOT_FOUND;
84adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  }
85adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
86adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  Catalog = (ELTORITO_CATALOG *) VolDescriptor;
87adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
88adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  //
89adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  // Loop: handle one volume descriptor per time
905d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  //       The ISO-9660 volume descriptor starts at 32k on the media
91adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  //
925d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin  for (VolDescriptorOffset = SIZE_32KB;
935d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin       VolDescriptorOffset <= MultU64x32 (Media->LastBlock, Media->BlockSize);
945d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin       VolDescriptorOffset += SIZE_2KB) {
9596f99e1df863aea8dc8ecadb29e799545c9d1924qhuang    Status = DiskIo->ReadDisk (
9696f99e1df863aea8dc8ecadb29e799545c9d1924qhuang                       DiskIo,
9796f99e1df863aea8dc8ecadb29e799545c9d1924qhuang                       Media->MediaId,
985d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin                       VolDescriptorOffset,
995d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin                       SIZE_2KB,
10096f99e1df863aea8dc8ecadb29e799545c9d1924qhuang                       VolDescriptor
10196f99e1df863aea8dc8ecadb29e799545c9d1924qhuang                       );
102adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    if (EFI_ERROR (Status)) {
103adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      Found = Status;
104adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      break;
105adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
106adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
107adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    // Check for valid volume descriptor signature
108adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
10988a19367979a28e41e88ef2c9637a0f41d1c3bc6vanjeff    if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||
11088a19367979a28e41e88ef2c9637a0f41d1c3bc6vanjeff        CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0
111adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        ) {
112adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      //
113adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      // end of Volume descriptor list
114adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      //
115adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      break;
116adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
117adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
118adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
119adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    // the 32-bit numerical values is stored in Both-byte orders
120adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
12188a19367979a28e41e88ef2c9637a0f41d1c3bc6vanjeff    if (VolDescriptor->PrimaryVolume.Type == CDVOL_TYPE_CODED) {
12288a19367979a28e41e88ef2c9637a0f41d1c3bc6vanjeff      VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[0];
123adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
124adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
125adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    // Is it an El Torito volume descriptor?
126adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
12788a19367979a28e41e88ef2c9637a0f41d1c3bc6vanjeff    if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {
128adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      continue;
129adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
130adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
131adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    // Read in the boot El Torito boot catalog
1325d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin    // The LBA unit used by El Torito boot catalog is 2KB unit
133adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
1345d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin    Lba2KB = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
1355d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin    // Ensure the LBA (in 2KB unit) fits into our media
1365d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin    if (Lba2KB * (SIZE_2KB / Media->BlockSize) > Media->LastBlock) {
137adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      continue;
138adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
139adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
14096f99e1df863aea8dc8ecadb29e799545c9d1924qhuang    Status = DiskIo->ReadDisk (
14196f99e1df863aea8dc8ecadb29e799545c9d1924qhuang                       DiskIo,
14296f99e1df863aea8dc8ecadb29e799545c9d1924qhuang                       Media->MediaId,
1435d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin                       MultU64x32 (Lba2KB, SIZE_2KB),
1445d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin                       SIZE_2KB,
14596f99e1df863aea8dc8ecadb29e799545c9d1924qhuang                       Catalog
14696f99e1df863aea8dc8ecadb29e799545c9d1924qhuang                       );
147adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    if (EFI_ERROR (Status)) {
148adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));
149adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      continue;
150adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
151adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
152adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    // We don't care too much about the Catalog header's contents, but we do want
153adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    // to make sure it looks like a Catalog header
154adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    //
155adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
156adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
157adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      continue;
158adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
159adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
160adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    Check       = 0;
161adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    CheckBuffer = (UINT16 *) Catalog;
162adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
163adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      Check += CheckBuffer[Index];
164adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
165adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
166ea7cb08c0afc7ad5dd9ed7176cd062385df8fa8bqhuang    if ((Check & 0xFFFF) != 0) {
167adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
168adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      continue;
169adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
170adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
171adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG);
172adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) {
173adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      //
174adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      // Next entry
175adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      //
176adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      Catalog += 1;
177adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
178adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      //
179adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      // Check this entry
180adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      //
181adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
182adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        continue;
183adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      }
184adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
185adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      SubBlockSize  = 512;
1865d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin      SectorCount   = Catalog->Boot.SectorCount * (SIZE_2KB / Media->BlockSize);
187adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
188adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      switch (Catalog->Boot.MediaType) {
189adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
190adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      case ELTORITO_NO_EMULATION:
191adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        SubBlockSize = Media->BlockSize;
192adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        break;
193adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
194adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      case ELTORITO_HARD_DISK:
195adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        break;
196adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
197adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      case ELTORITO_12_DISKETTE:
198adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        SectorCount = 0x50 * 0x02 * 0x0F;
199adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        break;
200adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
201adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      case ELTORITO_14_DISKETTE:
202adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        SectorCount = 0x50 * 0x02 * 0x12;
203adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        break;
204adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
205adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      case ELTORITO_28_DISKETTE:
206adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        SectorCount = 0x50 * 0x02 * 0x24;
207adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        break;
208adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
209adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      default:
210adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));
211adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        SectorCount   = 0;
212adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        SubBlockSize  = Media->BlockSize;
213adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        break;
214adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      }
215adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      //
216adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      // Create child device handle
217adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      //
218adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      CdDev.Header.Type     = MEDIA_DEVICE_PATH;
219adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      CdDev.Header.SubType  = MEDIA_CDROM_DP;
220adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));
221adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
222adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      if (Index == 1) {
223adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        //
224adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        // This is the initial/default entry
225adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        //
226adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        BootEntry = 0;
227adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      }
228adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
229adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      CdDev.BootEntry = (UINT32) BootEntry;
230adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      BootEntry++;
2315d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin      CdDev.PartitionStart = Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize);
232adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      if (SectorCount < 2) {
233adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        //
234adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        // When the SectorCount < 2, set the Partition as the whole CD.
235adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        //
236adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        if (VolSpaceSize > (Media->LastBlock + 1)) {
237adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff          CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba + 1);
238adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        } else {
239adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff          CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba);
240adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        }
241adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      } else {
242adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        CdDev.PartitionSize = DivU64x32 (
243adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                                MultU64x32 (
244adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                                  SectorCount,
245adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                                  SubBlockSize
246adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                                  ) + Media->BlockSize - 1,
247adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                                Media->BlockSize
248adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                                );
249adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      }
250adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
251adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      Status = PartitionInstallChildHandle (
252adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                This,
253adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                Handle,
254adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                DiskIo,
255493d8e3a5e86f78ef975e18dfa5754adce9e82deRuiyu Ni                DiskIo2,
256adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                BlockIo,
257490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang                BlockIo2,
258adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                DevicePath,
259adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
2605d6bf9e22973c2ad327ca7422f80144c848912dcOlivier Martin                Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize),
261173acde9162ad099005ef25456237c8a0e1b8d7fRuiyu Ni                MultU64x32 (Catalog->Boot.Lba + CdDev.PartitionSize - 1, SIZE_2KB / Media->BlockSize),
262adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                SubBlockSize,
263adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                FALSE
264adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff                );
265adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      if (!EFI_ERROR (Status)) {
266adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff        Found = EFI_SUCCESS;
267adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff      }
268adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff    }
269adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  }
270adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
271adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  FreePool (VolDescriptor);
272adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff
273adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff  return Found;
274adbcbf8ffcaedab483d23b52e8283aaad74cc807vanjeff}
275