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