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