]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c
Fixed bug in partition driver:
[mirror_edk2.git] / EdkModulePkg / Universal / Disk / Partition / Dxe / ElTorito.c
... / ...
CommitLineData
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\r
26EFI_STATUS\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 EFI_SUCCESS - some child handle(s) was added\r
48 EFI_MEDIA_CHANGED - Media changed Detected\r
49 !EFI_SUCCESS - 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 EFI_STATUS Found;\r
68 UINT32 VolSpaceSize;\r
69\r
70 Found = EFI_NOT_FOUND;\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 EFI_NOT_FOUND;\r
79 }\r
80\r
81 VolDescriptor = AllocatePool ((UINTN) Media->BlockSize);\r
82\r
83 if (VolDescriptor == NULL) {\r
84 return EFI_NOT_FOUND;\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 Found = Status;\r
119 break;\r
120 }\r
121 //\r
122 // Check for valid volume descriptor signature\r
123 //\r
124 if (VolDescriptor->Type == CDVOL_TYPE_END ||\r
125 CompareMem (VolDescriptor->Id, CDVOL_ID, sizeof (VolDescriptor->Id)) != 0\r
126 ) {\r
127 //\r
128 // end of Volume descriptor list\r
129 //\r
130 break;\r
131 }\r
132 //\r
133 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,\r
134 // the 32-bit numerical values is stored in Both-byte orders\r
135 //\r
136 if (VolDescriptor->Type == CDVOL_TYPE_CODED) {\r
137 VolSpaceSize = VolDescriptor->VolSpaceSize[0];\r
138 }\r
139 //\r
140 // Is it an El Torito volume descriptor?\r
141 //\r
142 if (CompareMem (VolDescriptor->SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {\r
143 continue;\r
144 }\r
145 //\r
146 // Read in the boot El Torito boot catalog\r
147 //\r
148 Lba = UNPACK_INT32 (VolDescriptor->EltCatalog);\r
149 if (Lba > Media->LastBlock) {\r
150 continue;\r
151 }\r
152\r
153 Status = BlockIo->ReadBlocks (\r
154 BlockIo,\r
155 Media->MediaId,\r
156 Lba,\r
157 Media->BlockSize,\r
158 Catalog\r
159 );\r
160 if (EFI_ERROR (Status)) {\r
161 DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));\r
162 continue;\r
163 }\r
164 //\r
165 // We don't care too much about the Catalog header's contents, but we do want\r
166 // to make sure it looks like a Catalog header\r
167 //\r
168 if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {\r
169 DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));\r
170 continue;\r
171 }\r
172\r
173 Check = 0;\r
174 CheckBuffer = (UINT16 *) Catalog;\r
175 for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {\r
176 Check += CheckBuffer[Index];\r
177 }\r
178\r
179 if (Check & 0xFFFF) {\r
180 DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));\r
181 continue;\r
182 }\r
183\r
184 MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG);\r
185 for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) {\r
186 //\r
187 // Next entry\r
188 //\r
189 Catalog += 1;\r
190\r
191 //\r
192 // Check this entry\r
193 //\r
194 if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {\r
195 continue;\r
196 }\r
197\r
198 SubBlockSize = 512;\r
199 SectorCount = Catalog->Boot.SectorCount;\r
200\r
201 switch (Catalog->Boot.MediaType) {\r
202\r
203 case ELTORITO_NO_EMULATION:\r
204 SubBlockSize = Media->BlockSize;\r
205 break;\r
206\r
207 case ELTORITO_HARD_DISK:\r
208 break;\r
209\r
210 case ELTORITO_12_DISKETTE:\r
211 SectorCount = 0x50 * 0x02 * 0x0F;\r
212 break;\r
213\r
214 case ELTORITO_14_DISKETTE:\r
215 SectorCount = 0x50 * 0x02 * 0x12;\r
216 break;\r
217\r
218 case ELTORITO_28_DISKETTE:\r
219 SectorCount = 0x50 * 0x02 * 0x24;\r
220 break;\r
221\r
222 default:\r
223 DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));\r
224 SectorCount = 0;\r
225 SubBlockSize = Media->BlockSize;\r
226 break;\r
227 }\r
228 //\r
229 // Create child device handle\r
230 //\r
231 CdDev.Header.Type = MEDIA_DEVICE_PATH;\r
232 CdDev.Header.SubType = MEDIA_CDROM_DP;\r
233 SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));\r
234\r
235 if (Index == 1) {\r
236 //\r
237 // This is the initial/default entry\r
238 //\r
239 BootEntry = 0;\r
240 }\r
241\r
242 CdDev.BootEntry = (UINT32) BootEntry;\r
243 BootEntry++;\r
244 CdDev.PartitionStart = Catalog->Boot.Lba;\r
245 if (SectorCount < 2) {\r
246 //\r
247 // When the SectorCount < 2, set the Partition as the whole CD.\r
248 //\r
249 if (VolSpaceSize > (Media->LastBlock + 1)) {\r
250 CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba + 1);\r
251 } else {\r
252 CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba);\r
253 }\r
254 } else {\r
255 CdDev.PartitionSize = DivU64x32 (\r
256 MultU64x32 (\r
257 SectorCount,\r
258 SubBlockSize\r
259 ) + Media->BlockSize - 1,\r
260 Media->BlockSize\r
261 );\r
262 }\r
263\r
264 Status = PartitionInstallChildHandle (\r
265 This,\r
266 Handle,\r
267 DiskIo,\r
268 BlockIo,\r
269 DevicePath,\r
270 (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,\r
271 Catalog->Boot.Lba,\r
272 Catalog->Boot.Lba + CdDev.PartitionSize - 1,\r
273 SubBlockSize,\r
274 FALSE\r
275 );\r
276 if (!EFI_ERROR (Status)) {\r
277 Found = EFI_SUCCESS;\r
278 }\r
279 }\r
280 }\r
281\r
282 gBS->FreePool (VolDescriptor);\r
283\r
284 return Found;\r
285}\r