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