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