OpenCorePkg/Platform/OpenLinuxBoot/LinuxBootInternal.h
Mike Beaton 6bb481ed62 OpenLinuxBoot: Fix booting with TuneD in Fedora 41
In GRUB2+blscfg mode:
 - Allow grub vars in 'initrd' as well as in 'options'
 - Allow multiple initrd files on one 'initrd' line
 - Initialise empty $tuned_params and $tuned_initrd grub vars if no
   values present, on an optional flag enabled by default (since
   we want to make booting major distros easy)

In GRUB2+blscfg mode (seem to be allowed now, not required for fix):
 - Allow multiple 'initrd' lines
 - Allow multiple 'options' lines

Add variant of OcParseVars which can parse as value-only tokens.

Signed-off-by: Mike Beaton <mjsbeaton@gmail.com>
2024-11-18 23:28:33 +00:00

405 lines
8.0 KiB
C

/** @file
Copyright (C) 2021, Mike Beaton. All rights reserved.<BR>
SPDX-License-Identifier: BSD-3-Clause
**/
#ifndef LINUX_BOOT_INTERNAL_H
#define LINUX_BOOT_INTERNAL_H
/*
Standard attached drives on OVMF appear as MBR, so it can be convenient when
debugging to allow entries with incorrect (i.e. specifies no/every drive)
root=... .
*/
// #define LINUX_ALLOW_MBR
#include <Uefi.h>
#include <Library/OcBootManagementLib.h>
#include <Library/OcMiscLib.h>
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
#define IS_ALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
/*
Allow scan of ESP.
*/
#define LINUX_BOOT_SCAN_ESP BIT0
/*
Allow scan of XBOOTLDR.
*/
#define LINUX_BOOT_SCAN_XBOOTLDR BIT1
/*
Allow scan of Linux Root filesystems.
*/
#define LINUX_BOOT_SCAN_LINUX_ROOT BIT2
/*
Allow scan of Linux Data filesystems.
*/
#define LINUX_BOOT_SCAN_LINUX_DATA BIT3
/*
Some space for additional file systems.
*/
/*
Allow scan of any filesystem not explicitly mentioned
(including but not limited FAT other than ESP, and NTFS).
*/
#define LINUX_BOOT_SCAN_OTHER BIT7
/*
Allow autodetect of vmlinuz-{version} and matching init*-{version},
if scan for usable /loader/entries fails.
*/
#define LINUX_BOOT_ALLOW_AUTODETECT BIT8
/*
Define entry id by the first part (to dash) of the filename
from which it was created. Results in the first matching entry (after sorting)
always being the default entry, which results in updated Linux becoming the
new default automatically.
*/
#define LINUX_BOOT_USE_LATEST BIT9
/*
If set, add "ro" as initial option to all distros. Can be specified per
FS by using argument autoopts:{partuuid}+=ro instead.
*/
#define LINUX_BOOT_ADD_RO BIT10
/*
If set, add "rw" as initial option to all distros. Can be specified per
FS by using argument autoopts:{partuuid}+=rw instead.
*/
#define LINUX_BOOT_ADD_RW BIT11
/*
TODO: (?) Both blspec-style and autodetect can make use of grub.cfg info if this flag is set.
These are currently parsed when needed for GRUB2+blscfg, i.e. if we find /loader/entries and /grub2/grub.cfg.
*/
// #define LINUX_BOOT_ALLOW_PARSE_GRUB BIT12
/*
Add root= option if missing in loader/entries *.conf options.
*/
#define LINUX_BOOT_ALLOW_CONF_AUTO_ROOT BIT13
/*
Add some additional log info.
*/
#define LINUX_BOOT_LOG_VERBOSE BIT14
/*
Prepend filesystem type and first 8 hex digits of PARTUUID to discovered
entry titles, to help in debugging where entries came from.
*/
#define LINUX_BOOT_ADD_DEBUG_INFO BIT15
/*
Trace grub var processing.
*/
#define LINUX_BOOT_LOG_GRUB_VARS BIT16
/*
Fix TuneD processing by initialising its grub variables if they are not present.
*/
#define LINUX_BOOT_FIX_TUNED BIT17
#define LINUX_BOOT_ALL ( \
LINUX_BOOT_SCAN_ESP | \
LINUX_BOOT_SCAN_XBOOTLDR | \
LINUX_BOOT_SCAN_LINUX_ROOT | \
LINUX_BOOT_SCAN_LINUX_DATA | \
LINUX_BOOT_SCAN_OTHER | \
LINUX_BOOT_ALLOW_AUTODETECT | \
LINUX_BOOT_USE_LATEST | \
LINUX_BOOT_ADD_RO | \
LINUX_BOOT_ADD_RW | \
LINUX_BOOT_ALLOW_CONF_AUTO_ROOT | \
LINUX_BOOT_LOG_VERBOSE | \
LINUX_BOOT_ADD_DEBUG_INFO | \
LINUX_BOOT_LOG_GRUB_VARS | \
LINUX_BOOT_FIX_TUNED \
)
/*
GRUB var error codes.
*/
#define VAR_ERR_NONE (0)
#define VAR_ERR_INDENTED BIT0 // Naive detection of GRUB conditional logic
#define VAR_ERR_HAS_VARS BIT1 // We do not support nested vars (in name or value), even though GRUB does
/*
Global flags for this instance of OpenLinuxBoot.efi.
*/
extern UINTN gLinuxBootFlags;
/*
Boot picker context.
*/
extern OC_PICKER_CONTEXT *gPickerContext;
/*
The array of loader entries, either really from *.conf files or generated by autodetect.
*/
extern OC_FLEX_ARRAY *gLoaderEntries;
/*
The current partuuid.
*/
extern EFI_GUID gPartuuid;
/*
Human readable ascii name of current file system type.
*/
extern CHAR8 *gFileSystemType;
// TODO: Are all of the below types used outside a single file?
// TODO: Is this file sensibly ordered?
/*
Forward declaration of GRUB_VAR structure.
*/
typedef struct GRUB_VAR_ GRUB_VAR;
/*
Forward declaration of LOADER_ENTRY structure.
*/
typedef struct LOADER_ENTRY_ LOADER_ENTRY;
/*
GRUB vars.
*/
EFI_STATUS
InternalInitGrubVars (
VOID
);
VOID
InternalFreeGrubVars (
VOID
);
EFI_STATUS
InternalSetGrubVar (
CHAR8 *Key,
CHAR8 *Value,
UINTN Errors
);
BOOLEAN
InternalHasGrubVars (
CHAR8 *Options
);
GRUB_VAR *
InternalGetGrubVar (
IN CONST CHAR8 *Key
);
EFI_STATUS
InternalExpandGrubVarsForArray (
IN OUT OC_FLEX_ARRAY *Options
);
EFI_STATUS
InternalExpandGrubVars (
IN CONST CHAR8 *Options,
IN OUT CHAR8 **Result
);
/*
Process grubenv file.
*/
EFI_STATUS
InternalProcessGrubEnv (
IN OUT CHAR8 *Content,
IN CONST UINTN Length
);
/*
Process grub.cfg file.
*/
EFI_STATUS
InternalProcessGrubCfg (
IN OUT CHAR8 *Content
);
LOADER_ENTRY *
InternalAllocateLoaderEntry (
VOID
);
VOID
InternalFreeLoaderEntry (
LOADER_ENTRY *Entry
);
EFI_STATUS
InternalProcessLoaderEntryFile (
IN CONST CHAR16 *FileName,
IN OUT CHAR8 *Content,
OUT LOADER_ENTRY *Entry,
IN CONST BOOLEAN Grub2
);
/*
GRUB variable.
*/
struct GRUB_VAR_ {
//
// Points within loaded file memory.
//
CHAR8 *Key;
//
// Points within loaded file memory, may be empty string.
//
CHAR8 *Value;
//
// GRUB var error code flags.
//
UINTN Errors;
};
/*
Loader entries.
*/
VOID
InternalFreePickerEntry (
IN OC_PICKER_ENTRY *Entry
);
EFI_STATUS
InternalConvertLoaderEntriesToBootEntries (
IN EFI_FILE_PROTOCOL *RootDirectory,
OUT OC_PICKER_ENTRY **Entries,
OUT UINTN *NumEntries
);
EFI_STATUS
InternalScanLoaderEntries (
IN EFI_FILE_PROTOCOL *RootDirectory,
OUT OC_PICKER_ENTRY **Entries,
OUT UINTN *NumEntries
);
EFI_STATUS
InternalIdVersionFromFileName (
IN OUT LOADER_ENTRY *Entry,
IN CHAR16 *FileName
);
/*
BLSpec / blscfg loader entry.
Some items within here probably don't need to be allocated and could stay
pointing within the source file as long as that is in memory (specifically
Version and Linux, which are probably never going to be modified), but to
keep things sane everything is (re)allocated.
*/
struct LOADER_ENTRY_ {
//
// Version.
// Must come first since used for sorting.
//
CHAR8 *Version;
//
// Title.
//
CHAR8 *Title;
//
// Linux kernel filename.
//
CHAR8 *Linux;
//
// Options.
//
OC_FLEX_ARRAY *Options;
//
// Initrds.
//
OC_FLEX_ARRAY *Initrds;
//
// OpenCore entry id.
// 'id' line is not read from .conf files even if present.
//
CHAR8 *OcId;
//
// Flavour.
//
CHAR8 *OcFlavour;
//
// Is this an auxiliary entry for OpenCore?
//
BOOLEAN OcAuxiliary;
//
// Has this already been scanned whilst assigned main and auxiliary entries?
//
BOOLEAN DuplicateIdScanned;
};
typedef struct VMLINUZ_FILE_ {
CHAR16 *FileName;
CHAR16 *Version;
UINTN StrLen;
} VMLINUZ_FILE;
/*
Autodetect options.
*/
typedef struct AUTOOPTS_ {
EFI_GUID Guid;
CHAR16 *Opts;
BOOLEAN PlusOpts;
} AUTOOPTS;
/*
Load autoopts.
*/
EFI_STATUS
InternalPreloadAutoOpts (
IN OC_FLEX_ARRAY *Options
);
/*
Autodetect.
*/
EFI_STATUS
InternalAutodetectLinux (
IN EFI_FILE_PROTOCOL *RootDirectory,
OUT OC_PICKER_ENTRY **Entries,
OUT UINTN *NumEntries
);
/*
Insert root=PARTUUID=... option.
*/
EFI_STATUS
InsertRootOption (
IN OC_FLEX_ARRAY *Options
);
/*
Sorts versions low to high.
*/
INTN
EFIAPI
InternalVersionCompare (
IN CONST VOID *Version1,
IN CONST VOID *Version2
);
/*
Sorts versions high to low.
*/
INTN
EFIAPI
InternalReverseVersionCompare (
IN CONST VOID *Version1,
IN CONST VOID *Version2
);
#endif // LINUX_BOOT_INTERNAL_H