OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
ElTorito.c
Go to the documentation of this file.
1
10#include "Partition.h"
11
29EFI_STATUS
31 IN EFI_DRIVER_BINDING_PROTOCOL *This,
32 IN EFI_HANDLE Handle,
33 IN EFI_DISK_IO_PROTOCOL *DiskIo,
34 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
35 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
36 IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
37 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
38 )
39{
40 EFI_STATUS Status;
41 UINT64 VolDescriptorOffset;
42 UINT32 Lba2KB;
43 EFI_BLOCK_IO_MEDIA *Media;
44 CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
45 ELTORITO_CATALOG *Catalog;
46 UINTN Check;
47 UINTN Index;
48 UINTN BootEntry;
49 UINTN MaxIndex;
50 UINT16 *CheckBuffer;
51 CDROM_DEVICE_PATH CdDev;
52 UINT32 SubBlockSize;
53 UINT32 SectorCount;
54 EFI_STATUS Found;
55 UINT32 VolSpaceSize;
56 EFI_PARTITION_INFO_PROTOCOL PartitionInfo;
57 APPLE_PARTITION_INFO_PROTOCOL ApplePartitionInfo;
58
59 Found = EFI_NOT_FOUND;
60 Media = BlockIo->Media;
61
62 VolSpaceSize = 0;
63
64 //
65 // CD_ROM has the fixed block size as 2048 bytes (SIZE_2KB)
66 //
67
68 // If the ISO image has been copied onto a different storage media
69 // then the block size might be different (eg: USB).
70 // Ensure 2048 (SIZE_2KB) is a multiple of block size
71 if (((SIZE_2KB % Media->BlockSize) != 0) || (Media->BlockSize > SIZE_2KB)) {
72 return EFI_NOT_FOUND;
73 }
74
75 VolDescriptor = AllocatePool ((UINTN)SIZE_2KB);
76
77 if (VolDescriptor == NULL) {
78 return EFI_NOT_FOUND;
79 }
80
81 Catalog = (ELTORITO_CATALOG *)VolDescriptor;
82
83 //
84 // Loop: handle one volume descriptor per time
85 // The ISO-9660 volume descriptor starts at 32k on the media
86 //
87 for (VolDescriptorOffset = SIZE_32KB;
88 VolDescriptorOffset <= MultU64x32 (Media->LastBlock, Media->BlockSize);
89 VolDescriptorOffset += SIZE_2KB)
90 {
91 Status = DiskIo->ReadDisk (
92 DiskIo,
93 Media->MediaId,
94 VolDescriptorOffset,
95 SIZE_2KB,
96 VolDescriptor
97 );
98 if (EFI_ERROR (Status)) {
99 Found = Status;
100 break;
101 }
102
103 //
104 // Check for valid volume descriptor signature
105 //
106 if ((VolDescriptor->Unknown.Type == CDVOL_TYPE_END) ||
107 (CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0)
108 )
109 {
110 //
111 // end of Volume descriptor list
112 //
113 break;
114 }
115
116 //
117 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
118 // the 32-bit numerical values is stored in Both-byte orders
119 //
120 if (VolDescriptor->PrimaryVolume.Type == CDVOL_TYPE_CODED) {
121 VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[0];
122 }
123
124 //
125 // Is it an El Torito volume descriptor?
126 //
127 if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {
128 continue;
129 }
130
131 //
132 // Read in the boot El Torito boot catalog
133 // The LBA unit used by El Torito boot catalog is 2KB unit
134 //
135 Lba2KB = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
136 // Ensure the LBA (in 2KB unit) fits into our media
137 if (Lba2KB * (SIZE_2KB / Media->BlockSize) > Media->LastBlock) {
138 continue;
139 }
140
141 Status = DiskIo->ReadDisk (
142 DiskIo,
143 Media->MediaId,
144 MultU64x32 (Lba2KB, SIZE_2KB),
145 SIZE_2KB,
146 Catalog
147 );
148 if (EFI_ERROR (Status)) {
149 DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));
150 continue;
151 }
152
153 //
154 // We don't care too much about the Catalog header's contents, but we do want
155 // to make sure it looks like a Catalog header
156 //
157 if ((Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG) || (Catalog->Catalog.Id55AA != 0xAA55)) {
158 DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
159 continue;
160 }
161
162 Check = 0;
163 CheckBuffer = (UINT16 *)Catalog;
164 for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
165 Check += CheckBuffer[Index];
166 }
167
168 if ((Check & 0xFFFF) != 0) {
169 DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
170 continue;
171 }
172
173 MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG);
174 for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) {
175 //
176 // Next entry
177 //
178 Catalog += 1;
179
180 //
181 // Check this entry
182 //
183 if ((Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE) || (Catalog->Boot.Lba == 0)) {
184 continue;
185 }
186
187 SubBlockSize = 512;
188 SectorCount = Catalog->Boot.SectorCount;
189
190 switch (Catalog->Boot.MediaType) {
191 case ELTORITO_NO_EMULATION:
192 SubBlockSize = Media->BlockSize;
193 break;
194
195 case ELTORITO_HARD_DISK:
196 break;
197
198 case ELTORITO_12_DISKETTE:
199 SectorCount = 0x50 * 0x02 * 0x0F;
200 break;
201
202 case ELTORITO_14_DISKETTE:
203 SectorCount = 0x50 * 0x02 * 0x12;
204 break;
205
206 case ELTORITO_28_DISKETTE:
207 SectorCount = 0x50 * 0x02 * 0x24;
208 break;
209
210 default:
211 DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));
212 SectorCount = 0;
213 SubBlockSize = Media->BlockSize;
214 break;
215 }
216
217 //
218 // Create child device handle
219 //
220 CdDev.Header.Type = MEDIA_DEVICE_PATH;
221 CdDev.Header.SubType = MEDIA_CDROM_DP;
222 SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));
223
224 if (Index == 1) {
225 //
226 // This is the initial/default entry
227 //
228 BootEntry = 0;
229 }
230
231 CdDev.BootEntry = (UINT32)BootEntry;
232 BootEntry++;
233 CdDev.PartitionStart = Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize);
234 if (SectorCount < 2) {
235 //
236 // When the SectorCount < 2, set the Partition as the whole CD.
237 //
238 if (VolSpaceSize * (SIZE_2KB / Media->BlockSize) > (Media->LastBlock + 1)) {
239 CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize) + 1);
240 } else {
241 CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba) * (SIZE_2KB / Media->BlockSize);
242 }
243 } else {
244 CdDev.PartitionSize = DivU64x32 (
245 MultU64x32 (
246 SectorCount * (SIZE_2KB / Media->BlockSize),
247 SubBlockSize
248 ) + Media->BlockSize - 1,
249 Media->BlockSize
250 );
251 }
252
253 ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
254 PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
255 PartitionInfo.Type = PARTITION_TYPE_OTHER;
256
257 ZeroMem (&ApplePartitionInfo, sizeof (APPLE_PARTITION_INFO_PROTOCOL));
258 ApplePartitionInfo.Revision = APPLE_PARTITION_INFO_REVISION;
259 ApplePartitionInfo.PartitionNumber = CdDev.BootEntry;
260 ApplePartitionInfo.PartitionStart = CdDev.PartitionStart;
261 ApplePartitionInfo.PartitionSize = CdDev.PartitionSize;
262
264 This,
265 Handle,
266 DiskIo,
267 DiskIo2,
268 BlockIo,
269 BlockIo2,
270 DevicePath,
271 (EFI_DEVICE_PATH_PROTOCOL *)&CdDev,
272 &PartitionInfo,
273 &ApplePartitionInfo,
274 Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize),
275 Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize) + CdDev.PartitionSize - 1,
276 SubBlockSize,
277 NULL
278 );
279 if (!EFI_ERROR (Status)) {
280 Found = EFI_SUCCESS;
281 }
282 }
283 }
284
285 FreePool (VolDescriptor);
286
287 return Found;
288}
#define APPLE_PARTITION_INFO_REVISION
EFI_STATUS PartitionInstallElToritoChildHandles(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition ElTorito.c:30
APPLE_EVENT_HANDLE Handle
Definition OcTypingLib.h:45
EFI_STATUS PartitionInstallChildHandle(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ParentHandle, IN EFI_DISK_IO_PROTOCOL *ParentDiskIo, IN EFI_DISK_IO2_PROTOCOL *ParentDiskIo2, IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo, IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, IN EFI_PARTITION_INFO_PROTOCOL *PartitionInfo, IN APPLE_PARTITION_INFO_PROTOCOL *ApplePartitionInfo, IN EFI_LBA Start, IN EFI_LBA End, IN UINT32 BlockSize, IN EFI_GUID *TypeGuid)
Definition Partition.c:1140
#define UNPACK_INT32(a)
Definition Partition.h:88
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition UserMath.c:96
#define DivU64x32(x, y, z)