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