OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OpenLinuxBoot.c
Go to the documentation of this file.
1
8#include "LinuxBootInternal.h"
9
10#include <Uefi.h>
11#include <Guid/Gpt.h>
12#include <Library/BaseLib.h>
13#include <Library/DevicePathLib.h>
14#include <Library/MemoryAllocationLib.h>
17#include <Library/OcFileLib.h>
19#include <Library/OcStringLib.h>
20#include <Library/UefiBootServicesTableLib.h>
21
23
25
27
30EFI_GUID gPartuuid;
32
33VOID
35 IN OC_PICKER_ENTRY *Entry
36 )
37{
38 ASSERT (Entry != NULL);
39
40 if (Entry == NULL) {
41 return;
42 }
43
44 //
45 // TODO: Is this un-CONST casting okay?
46 // (Are they CONST because they are not supposed to be freed when used as before?)
47 //
48 if (Entry->Id != NULL) {
49 FreePool ((CHAR8 *)Entry->Id);
50 }
51
52 if (Entry->Name != NULL) {
53 FreePool ((CHAR8 *)Entry->Name);
54 }
55
56 if (Entry->Path != NULL) {
57 FreePool ((CHAR8 *)Entry->Path);
58 }
59
60 if (Entry->Arguments != NULL) {
61 FreePool ((CHAR8 *)Entry->Arguments);
62 }
63
64 if (Entry->Flavour != NULL) {
65 FreePool ((CHAR8 *)Entry->Flavour);
66 }
67}
68
69STATIC
70VOID
71EFIAPI
73 IN OC_PICKER_ENTRY **Entries,
74 IN UINTN NumEntries
75 )
76{
77 UINTN Index;
78
79 ASSERT (Entries != NULL);
80 ASSERT (*Entries != NULL);
81 if ((Entries == NULL) || (*Entries == NULL)) {
82 return;
83 }
84
85 for (Index = 0; Index < NumEntries; Index++) {
86 InternalFreePickerEntry (&(*Entries)[Index]);
87 }
88
89 FreePool (*Entries);
90 *Entries = NULL;
91}
92
93STATIC
94EFI_STATUS
95EFIAPI
97 IN OUT OC_PICKER_CONTEXT *PickerContext,
98 IN CONST EFI_HANDLE Device OPTIONAL,
99 OUT OC_PICKER_ENTRY **Entries,
100 OUT UINTN *NumEntries
101 )
102{
103 EFI_STATUS Status;
104 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
105 EFI_FILE_PROTOCOL *RootDirectory;
106 UINT32 FileSystemPolicy;
107 CONST EFI_PARTITION_ENTRY *PartitionEntry;
108
109 ASSERT (PickerContext != NULL);
110 ASSERT (Entries != NULL);
111 ASSERT (NumEntries != NULL);
112
113 gPickerContext = PickerContext;
114 *Entries = NULL;
115 *NumEntries = 0;
116
117 //
118 // No custom entries.
119 //
120 if (Device == NULL) {
121 return EFI_NOT_FOUND;
122 }
123
124 //
125 // Open partition file system.
126 //
127 Status = gBS->HandleProtocol (
128 Device,
130 (VOID **)&FileSystem
131 );
132 if (EFI_ERROR (Status)) {
133 DEBUG ((DEBUG_WARN, "LNX: Missing filesystem - %r\n", Status));
134 return Status;
135 }
136
137 //
138 // Get handle to partiton root directory.
139 //
140 Status = FileSystem->OpenVolume (
141 FileSystem,
142 &RootDirectory
143 );
144 if (EFI_ERROR (Status)) {
145 DEBUG ((DEBUG_WARN, "LNX: Invalid root volume - %r\n", Status));
146 return Status;
147 }
148
149 gFileSystemType = NULL;
150
151 FileSystemPolicy = OcGetFileSystemPolicyType (Device);
152
153 //
154 // Disallow Apple filesystems, mainly to avoid needlessly
155 // scanning multiple APFS partitions.
156 //
157 if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_APFS) != 0) {
158 gFileSystemType = "APFS";
159 DEBUG ((DEBUG_INFO, "LNX: %a - not scanning\n", gFileSystemType));
160 Status = EFI_NOT_FOUND;
161 } else if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_HFS) != 0) {
162 gFileSystemType = "HFS";
163 DEBUG ((DEBUG_INFO, "LNX: %a - not scanning\n", gFileSystemType));
164 Status = EFI_NOT_FOUND;
165 } else if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_ESP) != 0) {
166 gFileSystemType = "ESP";
168 DEBUG ((DEBUG_INFO, "LNX: %a - requested not to scan\n", gFileSystemType));
169 Status = EFI_NOT_FOUND;
170 }
171 } else if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_XBOOTLDR) != 0) {
172 gFileSystemType = "XBOOTLDR";
174 DEBUG ((DEBUG_INFO, "LNX: %a - requested not to scan\n", gFileSystemType));
175 Status = EFI_NOT_FOUND;
176 }
177 } else if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_LINUX_ROOT) != 0) {
178 gFileSystemType = "LNX-R";
180 DEBUG ((DEBUG_INFO, "LNX: %a - requested not to scan\n", gFileSystemType));
181 Status = EFI_NOT_FOUND;
182 }
183 } else if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_LINUX_DATA) != 0) {
184 gFileSystemType = "LNX-D";
186 DEBUG ((DEBUG_INFO, "LNX: %a - requested not to scan\n", gFileSystemType));
187 Status = EFI_NOT_FOUND;
188 }
189 } else {
190 if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_NTFS) != 0) {
191 //
192 // This is not just NTFS, Msft Basic Data part type GUID is used for non-ESP FAT too.
193 //
194 gFileSystemType = "NTFS/FAT";
195 } else {
196 gFileSystemType = "OTHER";
197 }
198
200 DEBUG ((DEBUG_INFO, "LNX: %a - requested not to scan\n", gFileSystemType));
201 Status = EFI_NOT_FOUND;
202 }
203 }
204
205 if (EFI_ERROR (Status)) {
206 RootDirectory->Close (RootDirectory);
207 return Status;
208 }
209
210 //
211 // Save PARTUUID for autodetect.
212 //
213 PartitionEntry = OcGetGptPartitionEntry (Device);
214 if (PartitionEntry == NULL) {
215 CopyGuid (&gPartuuid, &gEfiPartTypeUnusedGuid);
216 } else {
217 CopyGuid (&gPartuuid, &PartitionEntry->UniquePartitionGUID);
218 }
219
220 //
221 // Log TypeGUID and PARTUUID of the drive we're in.
222 //
223 DEBUG ((
224 DEBUG_INFO,
225 "LNX: TypeGUID: %g (%a) PARTUUID: %g\n",
226 (PartitionEntry == NULL) ? &gEfiPartTypeUnusedGuid : &PartitionEntry->PartitionTypeGUID,
228 &gPartuuid
229 ));
230
231 //
232 // Scan for boot loader spec & blscfg entries (Fedora-like).
233 //
235 RootDirectory,
236 Entries,
237 NumEntries
238 );
239
240 //
241 // Note: As currently structured, will fall through to autodetect
242 // if no /loader/entries/*.conf files are present, but also if there
243 // are only unusable files in there.
244 //
245 if ( EFI_ERROR (Status)
247 {
248 //
249 // Auto-detect vmlinuz and initrd files on own root filesystem (Debian-like).
250 //
251 Status = InternalAutodetectLinux (
252 RootDirectory,
253 Entries,
254 NumEntries
255 );
256 }
257
258 RootDirectory->Close (RootDirectory);
259
260 return Status;
261}
262
263STATIC
271
272EFI_STATUS
273EFIAPI
275 IN EFI_HANDLE ImageHandle,
276 IN EFI_SYSTEM_TABLE *SystemTable
277 )
278{
279 EFI_STATUS Status;
280 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
281 UINTN AddBootFlags;
282 UINTN RemoveBootFlags;
283
284 Status = gBS->HandleProtocol (
285 ImageHandle,
287 (VOID **)&LoadedImage
288 );
289
290 if (EFI_ERROR (Status)) {
291 return Status;
292 }
293
294 //
295 // Keep mParsedLoadOptions kicking around, as all found options link into its memory.
296 //
297 Status = OcParseLoadOptions (LoadedImage, &mParsedLoadOptions);
298 if (!EFI_ERROR (Status)) {
299 AddBootFlags = 0;
300 RemoveBootFlags = 0;
303 OcParsedVarsGetInt (mParsedLoadOptions, L"flags-", &RemoveBootFlags, OcStringFormatUnicode);
304 gLinuxBootFlags |= AddBootFlags;
305 gLinuxBootFlags &= ~RemoveBootFlags;
306 } else {
307 if (Status != EFI_NOT_FOUND) {
308 return Status;
309 }
310
311 ASSERT (mParsedLoadOptions == NULL);
312 }
313
316
317 if (EFI_ERROR (Status)) {
318 return Status;
319 }
320 }
321
322 Status = gBS->InstallMultipleProtocolInterfaces (
323 &ImageHandle,
326 NULL
327 );
328
329 ASSERT_EFI_ERROR (Status);
330 if (EFI_ERROR (Status)) {
331 return Status;
332 }
333
334 return EFI_SUCCESS;
335}
EFI_STATUS InternalAutodetectLinux(IN EFI_FILE_PROTOCOL *RootDirectory, OUT OC_PICKER_ENTRY **Entries, OUT UINTN *NumEntries)
EFI_STATUS InternalPreloadAutoOpts(IN OC_FLEX_ARRAY *Options)
Definition Autodetect.c:489
#define LINUX_BOOT_SCAN_LINUX_ROOT
EFI_STATUS InternalScanLoaderEntries(IN EFI_FILE_PROTOCOL *RootDirectory, OUT OC_PICKER_ENTRY **Entries, OUT UINTN *NumEntries)
#define LINUX_BOOT_SCAN_XBOOTLDR
#define LINUX_BOOT_ALL
#define LINUX_BOOT_ADD_DEBUG_INFO
#define LINUX_BOOT_ADD_RW
#define LINUX_BOOT_SCAN_ESP
#define LINUX_BOOT_LOG_GRUB_VARS
#define LINUX_BOOT_ALLOW_AUTODETECT
#define LINUX_BOOT_SCAN_OTHER
#define LINUX_BOOT_SCAN_LINUX_DATA
#define LINUX_BOOT_LOG_VERBOSE
EFI_GUID gOcBootEntryProtocolGuid
#define OC_BOOT_ENTRY_PROTOCOL_REVISION
Definition OcBootEntry.h:31
UINT32 OcGetFileSystemPolicyType(IN EFI_HANDLE Handle)
#define OC_SCAN_ALLOW_FS_HFS
#define OC_SCAN_ALLOW_FS_LINUX_DATA
EFI_STATUS OcParseLoadOptions(IN CONST EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, OUT OC_FLEX_ARRAY **ParsedVars)
EFI_STATUS OcParsedVarsGetInt(IN CONST OC_FLEX_ARRAY *ParsedVars, IN CONST VOID *Name, OUT UINTN *Value, IN CONST OC_STRING_FORMAT StringFormat)
#define OC_SCAN_ALLOW_FS_LINUX_ROOT
#define OC_SCAN_ALLOW_FS_ESP
#define OC_SCAN_ALLOW_FS_APFS
#define OC_SCAN_ALLOW_FS_NTFS
#define OC_SCAN_ALLOW_FS_XBOOTLDR
EFI_BOOT_SERVICES * gBS
CONST EFI_PARTITION_ENTRY * OcGetGptPartitionEntry(IN EFI_HANDLE FsHandle)
Definition DiskMisc.c:732
@ OcStringFormatUnicode
Definition OcStringLib.h:51
STATIC OC_FLEX_ARRAY * mParsedLoadOptions
OC_FLEX_ARRAY * gLoaderEntries
EFI_GUID gPartuuid
VOID InternalFreePickerEntry(IN OC_PICKER_ENTRY *Entry)
EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
UINTN gLinuxBootFlags
STATIC OC_BOOT_ENTRY_PROTOCOL mLinuxBootEntryProtocol
CHAR8 * gFileSystemType
STATIC EFI_STATUS EFIAPI OcGetLinuxBootEntries(IN OUT OC_PICKER_CONTEXT *PickerContext, IN CONST EFI_HANDLE Device OPTIONAL, OUT OC_PICKER_ENTRY **Entries, OUT UINTN *NumEntries)
OC_PICKER_CONTEXT * gPickerContext
STATIC VOID EFIAPI OcFreeLinuxBootEntries(IN OC_PICKER_ENTRY **Entries, IN UINTN NumEntries)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
EFI_GUID gEfiSimpleFileSystemProtocolGuid
EFI_GUID gEfiLoadedImageProtocolGuid
#define ASSERT(x)
Definition coder.h:55