]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / PartitionDxe / ElTorito.c
... / ...
CommitLineData
1/** @file\r
2 Decode an El Torito formatted CD-ROM\r
3\r
4Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.\r
5Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "Partition.h"\r
11\r
12/**\r
13 Install child handles if the Handle supports El Torito format.\r
14\r
15 @param[in] This Calling context.\r
16 @param[in] Handle Parent Handle.\r
17 @param[in] DiskIo Parent DiskIo interface.\r
18 @param[in] DiskIo2 Parent DiskIo2 interface.\r
19 @param[in] BlockIo Parent BlockIo interface.\r
20 @param[in] BlockIo2 Parent BlockIo2 interface.\r
21 @param[in] DevicePath Parent Device Path\r
22\r
23\r
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
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
34 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,\r
35 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
36 IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,\r
37 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
38 )\r
39{\r
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
57\r
58 Found = EFI_NOT_FOUND;\r
59 Media = BlockIo->Media;\r
60\r
61 VolSpaceSize = 0;\r
62\r
63 //\r
64 // CD_ROM has the fixed block size as 2048 bytes (SIZE_2KB)\r
65 //\r
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
71 return EFI_NOT_FOUND;\r
72 }\r
73\r
74 VolDescriptor = AllocatePool ((UINTN)SIZE_2KB);\r
75\r
76 if (VolDescriptor == NULL) {\r
77 return EFI_NOT_FOUND;\r
78 }\r
79\r
80 Catalog = (ELTORITO_CATALOG *)VolDescriptor;\r
81\r
82 //\r
83 // Loop: handle one volume descriptor per time\r
84 // The ISO-9660 volume descriptor starts at 32k on the media\r
85 //\r
86 for (VolDescriptorOffset = SIZE_32KB;\r
87 VolDescriptorOffset <= MultU64x32 (Media->LastBlock, Media->BlockSize);\r
88 VolDescriptorOffset += SIZE_2KB)\r
89 {\r
90 Status = DiskIo->ReadDisk (\r
91 DiskIo,\r
92 Media->MediaId,\r
93 VolDescriptorOffset,\r
94 SIZE_2KB,\r
95 VolDescriptor\r
96 );\r
97 if (EFI_ERROR (Status)) {\r
98 Found = Status;\r
99 break;\r
100 }\r
101\r
102 //\r
103 // Check for valid volume descriptor signature\r
104 //\r
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
109 //\r
110 // end of Volume descriptor list\r
111 //\r
112 break;\r
113 }\r
114\r
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
119 if (VolDescriptor->PrimaryVolume.Type == CDVOL_TYPE_CODED) {\r
120 VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[0];\r
121 }\r
122\r
123 //\r
124 // Is it an El Torito volume descriptor?\r
125 //\r
126 if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {\r
127 continue;\r
128 }\r
129\r
130 //\r
131 // Read in the boot El Torito boot catalog\r
132 // The LBA unit used by El Torito boot catalog is 2KB unit\r
133 //\r
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
137 continue;\r
138 }\r
139\r
140 Status = DiskIo->ReadDisk (\r
141 DiskIo,\r
142 Media->MediaId,\r
143 MultU64x32 (Lba2KB, SIZE_2KB),\r
144 SIZE_2KB,\r
145 Catalog\r
146 );\r
147 if (EFI_ERROR (Status)) {\r
148 DEBUG ((DEBUG_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));\r
149 continue;\r
150 }\r
151\r
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
156 if ((Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG) || (Catalog->Catalog.Id55AA != 0xAA55)) {\r
157 DEBUG ((DEBUG_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));\r
158 continue;\r
159 }\r
160\r
161 Check = 0;\r
162 CheckBuffer = (UINT16 *)Catalog;\r
163 for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {\r
164 Check += CheckBuffer[Index];\r
165 }\r
166\r
167 if ((Check & 0xFFFF) != 0) {\r
168 DEBUG ((DEBUG_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));\r
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
182 if ((Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE) || (Catalog->Boot.Lba == 0)) {\r
183 continue;\r
184 }\r
185\r
186 SubBlockSize = 512;\r
187 SectorCount = Catalog->Boot.SectorCount;\r
188\r
189 switch (Catalog->Boot.MediaType) {\r
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
214 }\r
215\r
216 //\r
217 // Create child device handle\r
218 //\r
219 CdDev.Header.Type = MEDIA_DEVICE_PATH;\r
220 CdDev.Header.SubType = MEDIA_CDROM_DP;\r
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
230 CdDev.BootEntry = (UINT32)BootEntry;\r
231 BootEntry++;\r
232 CdDev.PartitionStart = Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize);\r
233 if (SectorCount < 2) {\r
234 //\r
235 // When the SectorCount < 2, set the Partition as the whole CD.\r
236 //\r
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
239 } else {\r
240 CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba) * (SIZE_2KB / Media->BlockSize);\r
241 }\r
242 } else {\r
243 CdDev.PartitionSize = DivU64x32 (\r
244 MultU64x32 (\r
245 SectorCount * (SIZE_2KB / Media->BlockSize),\r
246 SubBlockSize\r
247 ) + Media->BlockSize - 1,\r
248 Media->BlockSize\r
249 );\r
250 }\r
251\r
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
256 Status = PartitionInstallChildHandle (\r
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
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