2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/io/etfs.c
5 * PURPOSE: Boot Library El Torito File System Management Routines
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
12 #include "../drivers/filesystems/cdfs_new/cd.h"
13 typedef struct _RAW_ET_VD
20 ULONG BootCatalogOffset
;
22 } RAW_ET_VD
, *PRAW_ET_VD
;
24 /* DATA VARIABLES ************************************************************/
26 typedef struct _BL_ETFS_CONTEXT
33 PRAW_ISO_VD MemoryBlock
;
35 } BL_ETFS_CONTEXT
, *PBL_ETFS_CONTEXT
;
37 typedef struct _BL_ETFS_FILE
45 } BL_ETFS_FILE
, *PBL_ETFS_FILE
;
47 ULONG EtfsDeviceTableEntries
;
48 PVOID
* EtfsDeviceTable
;
52 _In_ PBL_FILE_ENTRY Directory
,
55 _Out_ PBL_FILE_ENTRY
*FileEntry
58 BL_FILE_CALLBACKS EtfsFunctionTable
=
63 /* FUNCTIONS *****************************************************************/
67 _In_ PBL_FILE_ENTRY Directory
,
70 _Out_ PBL_FILE_ENTRY
*FileEntry
73 EfiPrintf(L
"Attempting to open file %s in directory %s. Not yet supported\r\n", FileName
, Directory
->FilePath
);
74 return STATUS_NOT_IMPLEMENTED
;
79 _In_ PBL_ETFS_CONTEXT EtfsContext
,
81 _Out_ PRAW_ISO_VD
*VolumeDescriptor
,
82 _Out_ PBOOLEAN VolumeIsIso
85 EfiPrintf(L
"Raw Cdfs not implemented\r\n");
86 return STATUS_NOT_IMPLEMENTED
;
91 _In_ PBL_ETFS_CONTEXT EtfsContext
,
93 _Out_ PRAW_ISO_VD
*VolumeDescriptor
,
94 _Out_ PBOOLEAN VolumeIsIso
101 BL_DEVICE_INFORMATION DeviceInformation
;
102 ULONG Unknown
, BytesRead
;
103 ANSI_STRING CompareString
, String
;
105 /* Save our static buffer pointer */
106 IsoVd
= EtfsContext
->MemoryBlock
;
107 EtVd
= (PRAW_ET_VD
)IsoVd
;
109 /* First, read the El Torito Volume Descriptor */
110 BlDeviceGetInformation(DeviceId
, &DeviceInformation
);
111 Unknown
= DeviceInformation
.BlockDeviceInfo
.Unknown
;
112 DeviceInformation
.BlockDeviceInfo
.Unknown
|= 1;
113 BlDeviceSetInformation(DeviceId
, &DeviceInformation
);
114 Status
= BlDeviceReadAtOffset(DeviceId
,
116 (FIRST_VD_SECTOR
+ 1) * CD_SECTOR_SIZE
,
117 EtfsContext
->MemoryBlock
,
119 DeviceInformation
.BlockDeviceInfo
.Unknown
= Unknown
;
120 BlDeviceSetInformation(DeviceId
, &DeviceInformation
);
121 if (!NT_SUCCESS(Status
))
123 EfiPrintf(L
" read failed\r\n");
127 /* Remember that's where we last read */
128 EtfsContext
->Offset
= (FIRST_VD_SECTOR
+ 1) * CD_SECTOR_SIZE
;
130 /* Check if it's EL TORITO! */
131 RtlInitString(&String
, "EL TORITO SPECIFICATION");
132 CompareString
.Buffer
= (PCHAR
)EtVd
->SystemId
;
133 CompareString
.Length
= 23;
134 CompareString
.MaximumLength
= 23;
135 if (!RtlEqualString(&CompareString
, &String
, TRUE
))
137 return STATUS_UNSUCCESSFUL
;
140 /* Check the version and boot indicator */
141 if ((EtVd
->Version
!= 1) || (EtVd
->BootIndicator
))
143 return STATUS_UNSUCCESSFUL
;
146 /* Check if it has the CD0001 identifier */
147 RtlInitString(&String
, ISO_VOL_ID
);
148 CompareString
.Buffer
= (PCHAR
)EtVd
->StandardId
;
149 CompareString
.Length
= 5;
150 CompareString
.MaximumLength
= 5;
151 if (!RtlEqualString(&CompareString
, &String
, TRUE
))
153 return STATUS_UNSUCCESSFUL
;
156 /* Step two, we now want to read the ISO Volume Descriptor */
157 DeviceInformation
.BlockDeviceInfo
.Unknown
|= 1u;
158 BlDeviceSetInformation(DeviceId
, &DeviceInformation
);
159 Status
= BlDeviceReadAtOffset(DeviceId
,
161 FIRST_VD_SECTOR
* CD_SECTOR_SIZE
,
162 EtfsContext
->MemoryBlock
,
164 DeviceInformation
.BlockDeviceInfo
.Unknown
= Unknown
;
165 BlDeviceSetInformation(DeviceId
, &DeviceInformation
);
166 if (!NT_SUCCESS(Status
))
171 /* Remember where we left off */
172 EtfsContext
->Offset
= FIRST_VD_SECTOR
* CD_SECTOR_SIZE
;
174 /* This should also say CD0001 */
175 CompareString
.Buffer
= (PCHAR
)IsoVd
->StandardId
;
176 CompareString
.Length
= 5;
177 CompareString
.MaximumLength
= 5;
178 IsIso
= RtlEqualString(&CompareString
, &String
, TRUE
);
181 return STATUS_UNSUCCESSFUL
;
184 /* And should be a version we support */
185 if ((IsoVd
->Version
!= VERSION_1
) || (IsoVd
->DescType
!= VD_PRIMARY
))
187 return STATUS_UNSUCCESSFUL
;
190 /* Return back to the caller */
191 *VolumeDescriptor
= IsoVd
;
192 *VolumeIsIso
= IsIso
;
193 EfiPrintf(L
"Recognized!!!\r\n");
194 return STATUS_SUCCESS
;
198 EtfspGetDirectoryInfo (
199 _In_ PBL_ETFS_CONTEXT EtfsContext
,
200 _In_ PRAW_DIR_REC DirEntry
,
201 _Out_ PULONG FileOffset
,
202 _Out_ PULONG FileSize
,
203 _Out_opt_ PBOOLEAN IsDirectory
209 *FileOffset
= *(PULONG
)DirEntry
->FileLoc
* EtfsContext
->BlockSize
;
210 *FileOffset
+= (DirEntry
->XarLen
* EtfsContext
->BlockSize
);
212 SectorOffset
= ALIGN_DOWN_BY(*FileOffset
, CD_SECTOR_SIZE
);
214 *FileSize
= *(PULONG
)DirEntry
->DataLen
;
216 IsDir
= DE_FILE_FLAGS(EtfsContext
->IsIso
, DirEntry
) & ISO_ATTR_DIRECTORY
;
219 *FileSize
+= ALIGN_UP_BY(SectorOffset
, CD_SECTOR_SIZE
) - SectorOffset
;
224 *IsDirectory
= IsDir
;
229 EtfspDeviceContextDestroy (
230 _In_ PBL_ETFS_CONTEXT EtfsContext
233 if (EtfsContext
->MemoryBlock
)
235 BlMmFreeHeap(EtfsContext
->MemoryBlock
);
237 BlMmFreeHeap(EtfsContext
);
244 _Out_ PBL_ETFS_CONTEXT
*EtfsContext
247 PBL_ETFS_CONTEXT NewContext
;
253 NewContext
= (PBL_ETFS_CONTEXT
)BlMmAllocateHeap(sizeof(*NewContext
));
256 return STATUS_NO_MEMORY
;
258 RtlZeroMemory(NewContext
, sizeof(*NewContext
));
260 MemoryBlock
= BlMmAllocateHeap(CD_SECTOR_SIZE
);
261 NewContext
->MemoryBlock
= MemoryBlock
;
264 Status
= STATUS_NO_MEMORY
;
268 Status
= EtfspCheckEtfs(NewContext
, DeviceId
, &RawVd
, &IsIso
);
269 if (!NT_SUCCESS(Status
))
271 EfiPrintf(L
"Drive not EDFS. Checking for CDFS: %lx\r\n");
272 Status
= EtfspCheckCdfs(NewContext
, DeviceId
, &RawVd
, &IsIso
);
275 if (!NT_SUCCESS(Status
))
277 EfiPrintf(L
"Drive not CDFS. Failing: %lx\r\n");
281 NewContext
->IsIso
= IsIso
;
282 NewContext
->BlockSize
= RVD_LB_SIZE(RawVd
, IsIso
);
283 NewContext
->VolumeSize
= RVD_VOL_SIZE(RawVd
, IsIso
);
285 EtfspGetDirectoryInfo(NewContext
,
286 (PRAW_DIR_REC
)RVD_ROOT_DE(RawVd
, IsIso
),
287 &NewContext
->RootDirOffset
,
288 &NewContext
->RootDirSize
,
292 EtfspDeviceContextDestroy(NewContext
);
295 *EtfsContext
= NewContext
;
300 EtfspDeviceTableDestroyEntry (
301 _In_ PBL_ETFS_CONTEXT EtfsContext
,
305 EtfspDeviceContextDestroy(EtfsContext
);
306 EtfsDeviceTable
[Index
] = NULL
;
308 return STATUS_SUCCESS
;
315 _Out_ PBL_FILE_ENTRY
* FileEntry
318 PBL_ETFS_CONTEXT EtfsContext
= NULL
;
319 PBL_FILE_ENTRY RootEntry
;
321 PBL_ETFS_FILE EtfsFile
;
323 EfiPrintf(L
"Trying to mount as ETFS...\r\n");
325 Status
= EtfspCreateContext(DeviceId
, &EtfsContext
);
326 if (!NT_SUCCESS(Status
))
328 EfiPrintf(L
"ETFS context failed: %lx\r\n");
332 Status
= BlTblSetEntry(&EtfsDeviceTable
,
333 &EtfsDeviceTableEntries
,
337 if (!NT_SUCCESS(Status
))
339 EtfspDeviceContextDestroy(EtfsContext
);
343 RootEntry
= BlMmAllocateHeap(sizeof(*RootEntry
));
346 Status
= STATUS_NO_MEMORY
;
350 RtlZeroMemory(RootEntry
, sizeof(*RootEntry
));
352 RootEntry
->FilePath
= BlMmAllocateHeap(4);
353 if (!RootEntry
->FilePath
)
355 Status
= STATUS_NO_MEMORY
;
359 wcsncpy(RootEntry
->FilePath
, L
"\\", 1);
361 RootEntry
->DeviceId
= DeviceId
;
362 RtlCopyMemory(&RootEntry
->Callbacks
,
364 sizeof(RootEntry
->Callbacks
));
366 EtfsFile
= (PBL_ETFS_FILE
)BlMmAllocateHeap(sizeof(*EtfsFile
));
369 Status
= STATUS_NO_MEMORY
;
373 RootEntry
->Flags
|= 0x10000;
375 RtlZeroMemory(EtfsFile
, sizeof(*EtfsFile
));
376 RootEntry
->FsSpecificData
= EtfsFile
;
377 EtfsFile
->DeviceId
= DeviceId
;
378 EtfsFile
->Flags
|= 1;
379 EtfsFile
->Offset
= EtfsContext
->RootDirOffset
;
380 EtfsFile
->Unknown
= 0;
381 EtfsFile
->Size
= EtfsContext
->RootDirSize
;
382 EtfsFile
->FsName
= L
"cdfs";
383 *FileEntry
= RootEntry
;
385 return STATUS_SUCCESS
;
388 if (RootEntry
->FilePath
)
390 BlMmFreeHeap(RootEntry
->FilePath
);
392 if (RootEntry
->FsSpecificData
)
394 BlMmFreeHeap(RootEntry
->FsSpecificData
);
398 BlMmFreeHeap(RootEntry
);
401 EtfspDeviceTableDestroyEntry(EtfsContext
, DeviceId
);
413 /* Allocate the device table with 2 entries*/
414 EtfsDeviceTableEntries
= 2;
415 EtfsDeviceTable
= BlMmAllocateHeap(sizeof(PBL_FILE_ENTRY
) *
416 EtfsDeviceTableEntries
);
420 RtlZeroMemory(EtfsDeviceTable
,
421 sizeof(PBL_FILE_ENTRY
) * EtfsDeviceTableEntries
);
422 Status
= STATUS_SUCCESS
;
426 /* No memory, fail */
427 Status
= STATUS_NO_MEMORY
;
430 /* Return back to caller */