Слияние кода завершено, страница обновится автоматически
/** @file
OpenCore driver.
Copyright (c) 2019, vit9696. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/OcMainLib.h>
#include <Guid/OcVariable.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PrintLib.h>
#include <Library/OcCpuLib.h>
#include <Library/OcFileLib.h>
#include <Library/OcSerializeLib.h>
#include <Library/OcStringLib.h>
#include <Library/OcVariableLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
/**
Safe version check, documented in config.
**/
#define OC_NVRAM_STORAGE_VERSION 1
/**
Structure declaration for nvram file.
**/
#define OC_NVRAM_STORAGE_MAP_FIELDS(_, __) \
OC_MAP (OC_STRING, OC_ASSOC, _, __)
OC_DECLARE (OC_NVRAM_STORAGE_MAP)
#define OC_NVRAM_STORAGE_FIELDS(_, __) \
_(UINT32 , Version , , 0 , () ) \
_(OC_NVRAM_STORAGE_MAP , Add , , OC_CONSTR (OC_NVRAM_STORAGE_MAP, _, __) , OC_DESTR (OC_NVRAM_STORAGE_MAP))
OC_DECLARE (OC_NVRAM_STORAGE)
OC_MAP_STRUCTORS (OC_NVRAM_STORAGE_MAP)
OC_STRUCTORS (OC_NVRAM_STORAGE, ())
/**
Schema definition for nvram file.
**/
STATIC
OC_SCHEMA
mNvramStorageEntrySchema = OC_SCHEMA_MDATA (NULL);
STATIC
OC_SCHEMA
mNvramStorageAddSchema = OC_SCHEMA_MAP (NULL, &mNvramStorageEntrySchema);
STATIC
OC_SCHEMA
mNvramStorageNodesSchema[] = {
OC_SCHEMA_MAP_IN ("Add", OC_STORAGE_VAULT, Files, &mNvramStorageAddSchema),
OC_SCHEMA_INTEGER_IN ("Version", OC_STORAGE_VAULT, Version),
};
STATIC
OC_SCHEMA_INFO
mNvramStorageRootSchema = {
.Dict = {mNvramStorageNodesSchema, ARRAY_SIZE (mNvramStorageNodesSchema)}
};
STATIC
VOID
OcReportVersion (
IN OC_GLOBAL_CONFIG *Config
)
{
CONST CHAR8 *Version;
Version = OcMiscGetVersionString ();
DEBUG ((DEBUG_INFO, "OC: Current version is %a\n", Version));
if ((Config->Misc.Security.ExposeSensitiveData & OCS_EXPOSE_VERSION_VAR) != 0) {
OcSetSystemVariable (
OC_VERSION_VARIABLE_NAME,
OPEN_CORE_NVRAM_ATTR,
AsciiStrLen (Version),
(VOID *) Version,
NULL
);
} else {
OcSetSystemVariable (
OC_VERSION_VARIABLE_NAME,
OPEN_CORE_NVRAM_ATTR,
L_STR_LEN ("UNK-000-0000-00-00"),
"UNK-000-0000-00-00",
NULL
);
}
}
STATIC
EFI_STATUS
OcProcessVariableGuid (
IN CONST CHAR8 *AsciiVariableGuid,
OUT GUID *VariableGuid,
IN OC_NVRAM_LEGACY_MAP *Schema OPTIONAL,
OUT OC_NVRAM_LEGACY_ENTRY **SchemaEntry OPTIONAL
)
{
EFI_STATUS Status;
UINT32 GuidIndex;
Status = AsciiStrToGuid (AsciiVariableGuid, VariableGuid);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OC: Failed to convert NVRAM GUID %a - %r\n", AsciiVariableGuid, Status));
}
if (!EFI_ERROR (Status) && Schema != NULL) {
for (GuidIndex = 0; GuidIndex < Schema->Count; ++GuidIndex) {
if (AsciiStrCmp (AsciiVariableGuid, OC_BLOB_GET (Schema->Keys[GuidIndex])) == 0) {
*SchemaEntry = Schema->Values[GuidIndex];
return Status;
}
}
DEBUG ((DEBUG_INFO, "OC: Ignoring NVRAM GUID %a\n", AsciiVariableGuid));
Status = EFI_SECURITY_VIOLATION;
}
return Status;
}
STATIC
VOID
OcSetNvramVariable (
IN CONST CHAR8 *AsciiVariableName,
IN EFI_GUID *VariableGuid,
IN UINT32 Attributes,
IN UINT32 VariableSize,
IN VOID *VariableData,
IN OC_NVRAM_LEGACY_ENTRY *SchemaEntry,
IN BOOLEAN Overwrite
)
{
EFI_STATUS Status;
UINTN OriginalVariableSize;
CHAR16 *UnicodeVariableName;
BOOLEAN IsAllowed;
UINT32 VariableIndex;
VOID *OrgValue;
UINTN OrgSize;
UINT32 OrgAttributes;
if (SchemaEntry != NULL) {
IsAllowed = FALSE;
//
// TODO: Consider optimising lookup if it causes problems...
//
for (VariableIndex = 0; VariableIndex < SchemaEntry->Count; ++VariableIndex) {
if (VariableIndex == 0 && AsciiStrCmp ("*", OC_BLOB_GET (SchemaEntry->Values[VariableIndex])) == 0) {
IsAllowed = TRUE;
break;
}
if (AsciiStrCmp (AsciiVariableName, OC_BLOB_GET (SchemaEntry->Values[VariableIndex])) == 0) {
IsAllowed = TRUE;
break;
}
}
if (!IsAllowed) {
DEBUG ((DEBUG_INFO, "OC: Setting NVRAM %g:%a is not permitted\n", VariableGuid, AsciiVariableName));
return;
}
}
UnicodeVariableName = AsciiStrCopyToUnicode (AsciiVariableName, 0);
if (UnicodeVariableName == NULL) {
DEBUG ((DEBUG_WARN, "OC: Failed to convert NVRAM variable name %a\n", AsciiVariableName));
return;
}
OriginalVariableSize = 0;
Status = gRT->GetVariable (
UnicodeVariableName,
VariableGuid,
NULL,
&OriginalVariableSize,
NULL
);
if (Status == EFI_BUFFER_TOO_SMALL && Overwrite) {
Status = GetVariable3 (UnicodeVariableName, VariableGuid, &OrgValue, &OrgSize, &OrgAttributes);
if (!EFI_ERROR (Status)) {
//
// Do not allow overwriting BS-only variables. Ideally we also check for NV attribute,
// but it is not set by Duet.
//
if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS))
== (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) {
Status = gRT->SetVariable (UnicodeVariableName, VariableGuid, 0, 0, 0);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_INFO,
"OC: Failed to delete overwritten variable %g:%a - %r\n",
VariableGuid,
AsciiVariableName,
Status
));
Status = EFI_BUFFER_TOO_SMALL;
}
} else {
DEBUG ((
DEBUG_INFO,
"OC: Overwritten variable %g:%a has invalid attrs - %X\n",
VariableGuid,
AsciiVariableName,
Attributes
));
Status = EFI_BUFFER_TOO_SMALL;
}
FreePool (OrgValue);
} else {
DEBUG ((
DEBUG_INFO,
"OC: Overwritten variable %g:%a has unknown attrs - %r\n",
VariableGuid,
AsciiVariableName,
Status
));
Status = EFI_BUFFER_TOO_SMALL;
}
}
if (Status != EFI_BUFFER_TOO_SMALL) {
Status = gRT->SetVariable (
UnicodeVariableName,
VariableGuid,
Attributes,
VariableSize,
VariableData
);
DEBUG ((
EFI_ERROR (Status) && VariableSize > 0 ? DEBUG_WARN : DEBUG_INFO,
"OC: Setting NVRAM %g:%a - %r\n",
VariableGuid,
AsciiVariableName,
Status
));
} else {
DEBUG ((
DEBUG_INFO,
"OC: Setting NVRAM %g:%a - ignored, exists\n",
VariableGuid,
AsciiVariableName,
Status
));
}
FreePool (UnicodeVariableName);
}
STATIC
VOID
OcLoadLegacyNvram (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem,
IN OC_GLOBAL_CONFIG *Config
)
{
UINT8 *FileBuffer;
UINT32 FileSize;
OC_NVRAM_STORAGE Nvram;
BOOLEAN IsValid;
EFI_STATUS Status;
UINT32 GuidIndex;
UINT32 VariableIndex;
GUID VariableGuid;
OC_ASSOC *VariableMap;
OC_NVRAM_LEGACY_ENTRY *SchemaEntry;
OC_NVRAM_LEGACY_MAP *Schema;
Schema = &Config->Nvram.Legacy;
FileBuffer = OcReadFile (FileSystem, OPEN_CORE_NVRAM_PATH, &FileSize, BASE_1MB);
if (FileBuffer == NULL) {
DEBUG ((DEBUG_INFO, "OC: Invalid nvram data\n"));
return;
}
OC_NVRAM_STORAGE_CONSTRUCT (&Nvram, sizeof (Nvram));
IsValid = ParseSerialized (&Nvram, &mNvramStorageRootSchema, FileBuffer, FileSize, NULL);
FreePool (FileBuffer);
if (!IsValid || Nvram.Version != OC_NVRAM_STORAGE_VERSION) {
DEBUG ((
DEBUG_WARN,
"OC: Incompatible nvram data, version %u vs %d\n",
Nvram.Version,
OC_NVRAM_STORAGE_VERSION
));
OC_NVRAM_STORAGE_DESTRUCT (&Nvram, sizeof (Nvram));
return;
}
for (GuidIndex = 0; GuidIndex < Nvram.Add.Count; ++GuidIndex) {
Status = OcProcessVariableGuid (
OC_BLOB_GET (Nvram.Add.Keys[GuidIndex]),
&VariableGuid,
Schema,
&SchemaEntry
);
if (EFI_ERROR (Status)) {
continue;
}
VariableMap = Nvram.Add.Values[GuidIndex];
for (VariableIndex = 0; VariableIndex < VariableMap->Count; ++VariableIndex) {
OcSetNvramVariable (
OC_BLOB_GET (VariableMap->Keys[VariableIndex]),
&VariableGuid,
Config->Nvram.WriteFlash ? OPEN_CORE_NVRAM_NV_ATTR : OPEN_CORE_NVRAM_ATTR,
VariableMap->Values[VariableIndex]->Size,
OC_BLOB_GET (VariableMap->Values[VariableIndex]),
SchemaEntry,
Config->Nvram.LegacyOverwrite
);
}
}
OC_NVRAM_STORAGE_DESTRUCT (&Nvram, sizeof (Nvram));
}
STATIC
VOID
OcDeleteNvram (
IN OC_GLOBAL_CONFIG *Config
)
{
EFI_STATUS Status;
UINT32 DeleteGuidIndex;
UINT32 AddGuidIndex;
UINT32 DeleteVariableIndex;
UINT32 AddVariableIndex;
CONST CHAR8 *AsciiVariableName;
CHAR16 *UnicodeVariableName;
GUID VariableGuid;
OC_ASSOC *VariableMap;
VOID *CurrentValue;
UINTN CurrentValueSize;
BOOLEAN SameContents;
for (DeleteGuidIndex = 0; DeleteGuidIndex < Config->Nvram.Delete.Count; ++DeleteGuidIndex) {
Status = OcProcessVariableGuid (
OC_BLOB_GET (Config->Nvram.Delete.Keys[DeleteGuidIndex]),
&VariableGuid,
NULL,
NULL
);
if (EFI_ERROR (Status)) {
continue;
}
//
// When variable is set and non-volatile variable setting is used,
// we do not want a variable to be constantly removed and added every reboot,
// as it will negatively impact flash memory. In case the variable is already set
// and has the same value we do not delete it.
//
for (AddGuidIndex = 0; AddGuidIndex < Config->Nvram.Add.Count; ++AddGuidIndex) {
if (AsciiStrCmp (
OC_BLOB_GET (Config->Nvram.Delete.Keys[DeleteGuidIndex]),
OC_BLOB_GET (Config->Nvram.Add.Keys[AddGuidIndex])) == 0) {
break;
}
}
for (DeleteVariableIndex = 0; DeleteVariableIndex < Config->Nvram.Delete.Values[DeleteGuidIndex]->Count; ++DeleteVariableIndex) {
AsciiVariableName = OC_BLOB_GET (Config->Nvram.Delete.Values[DeleteGuidIndex]->Values[DeleteVariableIndex]);
//
// '#' is filtered in all keys, but for values we need to do it ourselves.
//
if (AsciiVariableName[0] == '#') {
DEBUG ((DEBUG_INFO, "OC: Variable skip deleting %a\n", AsciiVariableName));
continue;
}
UnicodeVariableName = AsciiStrCopyToUnicode (AsciiVariableName, 0);
if (UnicodeVariableName == NULL) {
DEBUG ((DEBUG_WARN, "OC: Failed to convert NVRAM variable name %a\n", AsciiVariableName));
continue;
}
if (AddGuidIndex != Config->Nvram.Add.Count) {
VariableMap = NULL;
for (AddVariableIndex = 0; AddVariableIndex < Config->Nvram.Add.Values[AddGuidIndex]->Count; ++AddVariableIndex) {
if (AsciiStrCmp (AsciiVariableName, OC_BLOB_GET (Config->Nvram.Add.Values[AddGuidIndex]->Keys[AddVariableIndex])) == 0) {
VariableMap = Config->Nvram.Add.Values[AddGuidIndex];
break;
}
}
if (VariableMap != NULL) {
Status = GetVariable2 (UnicodeVariableName, &VariableGuid, &CurrentValue, &CurrentValueSize);
if (!EFI_ERROR (Status)) {
SameContents = CurrentValueSize == VariableMap->Values[AddVariableIndex]->Size
&& CompareMem (OC_BLOB_GET (VariableMap->Values[AddVariableIndex]), CurrentValue, CurrentValueSize) == 0;
FreePool (CurrentValue);
} else if (Status == EFI_NOT_FOUND && VariableMap->Values[AddVariableIndex]->Size == 0) {
SameContents = TRUE;
} else {
SameContents = FALSE;
}
if (SameContents) {
DEBUG ((DEBUG_INFO, "OC: Not deleting NVRAM %g:%a, matches add\n", &VariableGuid, AsciiVariableName));
FreePool (UnicodeVariableName);
continue;
}
}
}
Status = gRT->SetVariable (UnicodeVariableName, &VariableGuid, 0, 0, 0);
DEBUG ((
EFI_ERROR (Status) && Status != EFI_NOT_FOUND ? DEBUG_WARN : DEBUG_INFO,
"OC: Deleting NVRAM %g:%a - %r\n",
&VariableGuid,
AsciiVariableName,
Status
));
FreePool (UnicodeVariableName);
}
}
}
STATIC
VOID
OcAddNvram (
IN OC_GLOBAL_CONFIG *Config
)
{
EFI_STATUS Status;
UINT32 GuidIndex;
UINT32 VariableIndex;
GUID VariableGuid;
OC_ASSOC *VariableMap;
for (GuidIndex = 0; GuidIndex < Config->Nvram.Add.Count; ++GuidIndex) {
Status = OcProcessVariableGuid (
OC_BLOB_GET (Config->Nvram.Add.Keys[GuidIndex]),
&VariableGuid,
NULL,
NULL
);
if (EFI_ERROR (Status)) {
continue;
}
VariableMap = Config->Nvram.Add.Values[GuidIndex];
for (VariableIndex = 0; VariableIndex < VariableMap->Count; ++VariableIndex) {
OcSetNvramVariable (
OC_BLOB_GET (VariableMap->Keys[VariableIndex]),
&VariableGuid,
Config->Nvram.WriteFlash ? OPEN_CORE_NVRAM_NV_ATTR : OPEN_CORE_NVRAM_ATTR,
VariableMap->Values[VariableIndex]->Size,
OC_BLOB_GET (VariableMap->Values[VariableIndex]),
NULL,
FALSE
);
}
}
}
VOID
OcLoadNvramSupport (
IN OC_STORAGE_CONTEXT *Storage,
IN OC_GLOBAL_CONFIG *Config
)
{
if (Config->Nvram.LegacyEnable && Storage->FileSystem != NULL) {
OcLoadLegacyNvram (Storage->FileSystem, Config);
}
OcDeleteNvram (Config);
OcAddNvram (Config);
OcReportVersion (Config);
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )