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