blob: 316807497dd4007c61c835d2e30efeda652005fa (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/** @file
Driver entry point
Copyright (c) 2021 Pedro Falcato All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "Ext4Dxe.h"
/**
Opens an ext4 partition and installs the Simple File System protocol.
@param[in] DeviceHandle Handle to the block device.
@param[in] DiskIo Pointer to an EFI_DISK_IO_PROTOCOL.
@param[in opt] DiskIo2 Pointer to an EFI_DISK_IO2_PROTOCOL, if supported.
@param[in] BlockIo Pointer to an EFI_BLOCK_IO_PROTOCOL.
@retval EFI_SUCCESS The opening was successful.
!EFI_SUCCESS Opening failed.
**/
EFI_STATUS
Ext4OpenPartition (
IN EFI_HANDLE DeviceHandle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
IN OPTIONAL EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo
)
{
EXT4_PARTITION *Part;
EFI_STATUS Status;
Part = AllocateZeroPool (sizeof (*Part));
if (Part == NULL) {
return EFI_OUT_OF_RESOURCES;
}
InitializeListHead (&Part->OpenFiles);
Part->BlockIo = BlockIo;
Part->DiskIo = DiskIo;
Part->DiskIo2 = DiskIo2;
Status = Ext4OpenSuperblock (Part);
if (EFI_ERROR (Status)) {
FreePool (Part);
return Status;
}
Part->Interface.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
Part->Interface.OpenVolume = Ext4OpenVolume;
Status = gBS->InstallMultipleProtocolInterfaces (
&DeviceHandle,
&gEfiSimpleFileSystemProtocolGuid,
&Part->Interface,
NULL
);
if (EFI_ERROR (Status)) {
FreePool (Part);
return Status;
}
return EFI_SUCCESS;
}
/**
Sets up the protocol and metadata of a file that is being opened.
@param[in out] File Pointer to the file.
@param[in] Partition Pointer to the opened partition.
**/
VOID
Ext4SetupFile (
IN OUT EXT4_FILE *File,
IN EXT4_PARTITION *Partition
)
{
// Note: We don't yet support revision 2 of the file protocol
// (needs DISK_IO2 + asynchronous IO)
File->Protocol.Revision = EFI_FILE_PROTOCOL_REVISION;
File->Protocol.Open = Ext4Open;
File->Protocol.Close = Ext4Close;
File->Protocol.Delete = Ext4Delete;
File->Protocol.Read = Ext4ReadFile;
File->Protocol.Write = Ext4WriteFile;
File->Protocol.SetPosition = Ext4SetPosition;
File->Protocol.GetPosition = Ext4GetPosition;
File->Protocol.GetInfo = Ext4GetInfo;
File->Protocol.SetInfo = Ext4SetInfo;
File->Partition = Partition;
}
/**
Unmounts and frees an ext4 partition.
@param[in] Partition Pointer to the opened partition.
@retval Status of the unmount.
**/
EFI_STATUS
Ext4UnmountAndFreePartition (
IN EXT4_PARTITION *Partition
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *NextEntry;
EXT4_FILE *File;
BOOLEAN DeletedRootDentry;
Partition->Unmounting = TRUE;
Ext4CloseInternal (Partition->Root);
BASE_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Partition->OpenFiles) {
File = EXT4_FILE_FROM_OPEN_FILES_NODE (Entry);
Ext4CloseInternal (File);
}
DeletedRootDentry = Ext4UnrefDentry (Partition->RootDentry);
if (!DeletedRootDentry) {
DEBUG ((DEBUG_ERROR, "[ext4] Failed to delete root dentry - resource leak present.\n"));
}
FreePool (Partition->BlockGroups);
FreePool (Partition);
return EFI_SUCCESS;
}
|