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