]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c
MdeModulePkg/PartitionDxe: Add partition type guid to installed handle
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / PartitionDxe / ElTorito.c
1 /** @file
2 Decode an El Torito formatted CD-ROM
3
4 Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.
5 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include "Partition.h"
18
19
20 /**
21 Install child handles if the Handle supports El Torito format.
22
23 @param[in] This Calling context.
24 @param[in] Handle Parent Handle.
25 @param[in] DiskIo Parent DiskIo interface.
26 @param[in] DiskIo2 Parent DiskIo2 interface.
27 @param[in] BlockIo Parent BlockIo interface.
28 @param[in] BlockIo2 Parent BlockIo2 interface.
29 @param[in] DevicePath Parent Device Path
30
31
32 @retval EFI_SUCCESS Child handle(s) was added.
33 @retval EFI_MEDIA_CHANGED Media changed Detected.
34 @retval other no child handle was added.
35
36 **/
37 EFI_STATUS
38 PartitionInstallElToritoChildHandles (
39 IN EFI_DRIVER_BINDING_PROTOCOL *This,
40 IN EFI_HANDLE Handle,
41 IN EFI_DISK_IO_PROTOCOL *DiskIo,
42 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
43 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
44 IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
45 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
46 )
47 {
48 EFI_STATUS Status;
49 UINT64 VolDescriptorOffset;
50 UINT32 Lba2KB;
51 EFI_BLOCK_IO_MEDIA *Media;
52 CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
53 ELTORITO_CATALOG *Catalog;
54 UINTN Check;
55 UINTN Index;
56 UINTN BootEntry;
57 UINTN MaxIndex;
58 UINT16 *CheckBuffer;
59 CDROM_DEVICE_PATH CdDev;
60 UINT32 SubBlockSize;
61 UINT32 SectorCount;
62 EFI_STATUS Found;
63 UINT32 VolSpaceSize;
64 EFI_PARTITION_INFO_PROTOCOL PartitionInfo;
65
66 Found = EFI_NOT_FOUND;
67 Media = BlockIo->Media;
68
69 VolSpaceSize = 0;
70
71 //
72 // CD_ROM has the fixed block size as 2048 bytes (SIZE_2KB)
73 //
74
75 // If the ISO image has been copied onto a different storage media
76 // then the block size might be different (eg: USB).
77 // Ensure 2048 (SIZE_2KB) is a multiple of block size
78 if (((SIZE_2KB % Media->BlockSize) != 0) || (Media->BlockSize > SIZE_2KB)) {
79 return EFI_NOT_FOUND;
80 }
81
82 VolDescriptor = AllocatePool ((UINTN)SIZE_2KB);
83
84 if (VolDescriptor == NULL) {
85 return EFI_NOT_FOUND;
86 }
87
88 Catalog = (ELTORITO_CATALOG *) VolDescriptor;
89
90 //
91 // Loop: handle one volume descriptor per time
92 // The ISO-9660 volume descriptor starts at 32k on the media
93 //
94 for (VolDescriptorOffset = SIZE_32KB;
95 VolDescriptorOffset <= MultU64x32 (Media->LastBlock, Media->BlockSize);
96 VolDescriptorOffset += SIZE_2KB) {
97 Status = DiskIo->ReadDisk (
98 DiskIo,
99 Media->MediaId,
100 VolDescriptorOffset,
101 SIZE_2KB,
102 VolDescriptor
103 );
104 if (EFI_ERROR (Status)) {
105 Found = Status;
106 break;
107 }
108 //
109 // Check for valid volume descriptor signature
110 //
111 if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||
112 CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0
113 ) {
114 //
115 // end of Volume descriptor list
116 //
117 break;
118 }
119 //
120 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
121 // the 32-bit numerical values is stored in Both-byte orders
122 //
123 if (VolDescriptor->PrimaryVolume.Type == CDVOL_TYPE_CODED) {
124 VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[0];
125 }
126 //
127 // Is it an El Torito volume descriptor?
128 //
129 if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {
130 continue;
131 }
132 //
133 // Read in the boot El Torito boot catalog
134 // The LBA unit used by El Torito boot catalog is 2KB unit
135 //
136 Lba2KB = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
137 // Ensure the LBA (in 2KB unit) fits into our media
138 if (Lba2KB * (SIZE_2KB / Media->BlockSize) > Media->LastBlock) {
139 continue;
140 }
141
142 Status = DiskIo->ReadDisk (
143 DiskIo,
144 Media->MediaId,
145 MultU64x32 (Lba2KB, SIZE_2KB),
146 SIZE_2KB,
147 Catalog
148 );
149 if (EFI_ERROR (Status)) {
150 DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));
151 continue;
152 }
153 //
154 // We don't care too much about the Catalog header's contents, but we do want
155 // to make sure it looks like a Catalog header
156 //
157 if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
158 DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
159 continue;
160 }
161
162 Check = 0;
163 CheckBuffer = (UINT16 *) Catalog;
164 for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
165 Check += CheckBuffer[Index];
166 }
167
168 if ((Check & 0xFFFF) != 0) {
169 DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
170 continue;
171 }
172
173 MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG);
174 for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) {
175 //
176 // Next entry
177 //
178 Catalog += 1;
179
180 //
181 // Check this entry
182 //
183 if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
184 continue;
185 }
186
187 SubBlockSize = 512;
188 SectorCount = Catalog->Boot.SectorCount;
189
190 switch (Catalog->Boot.MediaType) {
191
192 case ELTORITO_NO_EMULATION:
193 SubBlockSize = Media->BlockSize;
194 break;
195
196 case ELTORITO_HARD_DISK:
197 break;
198
199 case ELTORITO_12_DISKETTE:
200 SectorCount = 0x50 * 0x02 * 0x0F;
201 break;
202
203 case ELTORITO_14_DISKETTE:
204 SectorCount = 0x50 * 0x02 * 0x12;
205 break;
206
207 case ELTORITO_28_DISKETTE:
208 SectorCount = 0x50 * 0x02 * 0x24;
209 break;
210
211 default:
212 DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));
213 SectorCount = 0;
214 SubBlockSize = Media->BlockSize;
215 break;
216 }
217 //
218 // Create child device handle
219 //
220 CdDev.Header.Type = MEDIA_DEVICE_PATH;
221 CdDev.Header.SubType = MEDIA_CDROM_DP;
222 SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));
223
224 if (Index == 1) {
225 //
226 // This is the initial/default entry
227 //
228 BootEntry = 0;
229 }
230
231 CdDev.BootEntry = (UINT32) BootEntry;
232 BootEntry++;
233 CdDev.PartitionStart = Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize);
234 if (SectorCount < 2) {
235 //
236 // When the SectorCount < 2, set the Partition as the whole CD.
237 //
238 if (VolSpaceSize * (SIZE_2KB / Media->BlockSize) > (Media->LastBlock + 1)) {
239 CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize) + 1);
240 } else {
241 CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba) * (SIZE_2KB / Media->BlockSize);
242 }
243 } else {
244 CdDev.PartitionSize = DivU64x32 (
245 MultU64x32 (
246 SectorCount * (SIZE_2KB / Media->BlockSize),
247 SubBlockSize
248 ) + Media->BlockSize - 1,
249 Media->BlockSize
250 );
251 }
252
253 ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
254 PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
255 PartitionInfo.Type = PARTITION_TYPE_OTHER;
256
257 Status = PartitionInstallChildHandle (
258 This,
259 Handle,
260 DiskIo,
261 DiskIo2,
262 BlockIo,
263 BlockIo2,
264 DevicePath,
265 (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
266 &PartitionInfo,
267 Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize),
268 Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize) + CdDev.PartitionSize - 1,
269 SubBlockSize,
270 NULL
271 );
272 if (!EFI_ERROR (Status)) {
273 Found = EFI_SUCCESS;
274 }
275 }
276 }
277
278 FreePool (VolDescriptor);
279
280 return Found;
281 }