mirror of https://github.com/acidanthera/audk.git
423 lines
11 KiB
C
423 lines
11 KiB
C
/** @file
|
|
Internal file explorer functions for SecureBoot configuration module.
|
|
|
|
Copyright (c) 2012 - 2016, Intel Corporation. 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 "SecureBootConfigImpl.h"
|
|
|
|
VOID *mStartOpCodeHandle = NULL;
|
|
VOID *mEndOpCodeHandle = NULL;
|
|
EFI_IFR_GUID_LABEL *mStartLabel = NULL;
|
|
EFI_IFR_GUID_LABEL *mEndLabel = NULL;
|
|
|
|
/**
|
|
Refresh the global UpdateData structure.
|
|
|
|
**/
|
|
VOID
|
|
RefreshUpdateData (
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Free current updated date
|
|
//
|
|
if (mStartOpCodeHandle != NULL) {
|
|
HiiFreeOpCodeHandle (mStartOpCodeHandle);
|
|
}
|
|
|
|
//
|
|
// Create new OpCode Handle
|
|
//
|
|
mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
|
|
|
|
//
|
|
// Create Hii Extend Label OpCode as the start opcode
|
|
//
|
|
mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
|
|
mStartOpCodeHandle,
|
|
&gEfiIfrTianoGuid,
|
|
NULL,
|
|
sizeof (EFI_IFR_GUID_LABEL)
|
|
);
|
|
mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
|
|
}
|
|
|
|
/**
|
|
Clean up the dynamic opcode at label and form specified by both LabelId.
|
|
|
|
@param[in] LabelId It is both the Form ID and Label ID for opcode deletion.
|
|
@param[in] PrivateData Module private data.
|
|
|
|
**/
|
|
VOID
|
|
CleanUpPage (
|
|
IN UINT16 LabelId,
|
|
IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData
|
|
)
|
|
{
|
|
RefreshUpdateData ();
|
|
|
|
//
|
|
// Remove all op-codes from dynamic page
|
|
//
|
|
mStartLabel->Number = LabelId;
|
|
HiiUpdateForm (
|
|
PrivateData->HiiHandle,
|
|
&gSecureBootConfigFormSetGuid,
|
|
LabelId,
|
|
mStartOpCodeHandle, // Label LabelId
|
|
mEndOpCodeHandle // LABEL_END
|
|
);
|
|
}
|
|
|
|
/**
|
|
This function will open a file or directory referenced by DevicePath.
|
|
|
|
This function opens a file with the open mode according to the file path. The
|
|
Attributes is valid only for EFI_FILE_MODE_CREATE.
|
|
|
|
@param[in, out] FilePath On input, the device path to the file.
|
|
On output, the remaining device path.
|
|
@param[out] FileHandle Pointer to the file handle.
|
|
@param[in] OpenMode The mode to open the file with.
|
|
@param[in] Attributes The file's file attributes.
|
|
|
|
@retval EFI_SUCCESS The information was set.
|
|
@retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
|
|
@retval EFI_UNSUPPORTED Could not open the file path.
|
|
@retval EFI_NOT_FOUND The specified file could not be found on the
|
|
device or the file system could not be found on
|
|
the device.
|
|
@retval EFI_NO_MEDIA The device has no medium.
|
|
@retval EFI_MEDIA_CHANGED The device has a different medium in it or the
|
|
medium is no longer supported.
|
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
|
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
|
|
@retval EFI_WRITE_PROTECTED The file or medium is write protected.
|
|
@retval EFI_ACCESS_DENIED The file was opened read only.
|
|
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
|
|
file.
|
|
@retval EFI_VOLUME_FULL The volume is full.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
OpenFileByDevicePath(
|
|
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
|
|
OUT EFI_FILE_HANDLE *FileHandle,
|
|
IN UINT64 OpenMode,
|
|
IN UINT64 Attributes
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
|
|
EFI_FILE_PROTOCOL *Handle1;
|
|
EFI_FILE_PROTOCOL *Handle2;
|
|
EFI_HANDLE DeviceHandle;
|
|
|
|
if ((FilePath == NULL || FileHandle == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = gBS->LocateDevicePath (
|
|
&gEfiSimpleFileSystemProtocolGuid,
|
|
FilePath,
|
|
&DeviceHandle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = gBS->OpenProtocol(
|
|
DeviceHandle,
|
|
&gEfiSimpleFileSystemProtocolGuid,
|
|
(VOID**)&EfiSimpleFileSystemProtocol,
|
|
gImageHandle,
|
|
NULL,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
|
|
if (EFI_ERROR (Status)) {
|
|
FileHandle = NULL;
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// go down directories one node at a time.
|
|
//
|
|
while (!IsDevicePathEnd (*FilePath)) {
|
|
//
|
|
// For file system access each node should be a file path component
|
|
//
|
|
if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||
|
|
DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
|
|
) {
|
|
FileHandle = NULL;
|
|
return (EFI_INVALID_PARAMETER);
|
|
}
|
|
//
|
|
// Open this file path node
|
|
//
|
|
Handle2 = Handle1;
|
|
Handle1 = NULL;
|
|
|
|
//
|
|
// Try to test opening an existing file
|
|
//
|
|
Status = Handle2->Open (
|
|
Handle2,
|
|
&Handle1,
|
|
((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
|
|
OpenMode &~EFI_FILE_MODE_CREATE,
|
|
0
|
|
);
|
|
|
|
//
|
|
// see if the error was that it needs to be created
|
|
//
|
|
if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
|
|
Status = Handle2->Open (
|
|
Handle2,
|
|
&Handle1,
|
|
((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
|
|
OpenMode,
|
|
Attributes
|
|
);
|
|
}
|
|
//
|
|
// Close the last node
|
|
//
|
|
Handle2->Close (Handle2);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
return (Status);
|
|
}
|
|
|
|
//
|
|
// Get the next node
|
|
//
|
|
*FilePath = NextDevicePathNode (*FilePath);
|
|
}
|
|
|
|
//
|
|
// This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
|
|
//
|
|
*FileHandle = (VOID*)Handle1;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
|
|
The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL
|
|
means not enough memory resource.
|
|
|
|
@param DevicePath Device path.
|
|
|
|
@retval NULL Not enough memory resourece for AllocateCopyPool.
|
|
@retval Other A new allocated string that represents the file name.
|
|
|
|
**/
|
|
CHAR16 *
|
|
ExtractFileNameFromDevicePath (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
)
|
|
{
|
|
CHAR16 *String;
|
|
CHAR16 *MatchString;
|
|
CHAR16 *LastMatch;
|
|
CHAR16 *FileName;
|
|
UINTN Length;
|
|
|
|
ASSERT(DevicePath != NULL);
|
|
|
|
String = DevicePathToStr(DevicePath);
|
|
MatchString = String;
|
|
LastMatch = String;
|
|
FileName = NULL;
|
|
|
|
while(MatchString != NULL){
|
|
LastMatch = MatchString + 1;
|
|
MatchString = StrStr(LastMatch,L"\\");
|
|
}
|
|
|
|
Length = StrLen(LastMatch);
|
|
FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
|
|
if (FileName != NULL) {
|
|
*(FileName + Length) = 0;
|
|
}
|
|
|
|
FreePool(String);
|
|
|
|
return FileName;
|
|
}
|
|
|
|
|
|
/**
|
|
Update the form base on the selected file.
|
|
|
|
@param FilePath Point to the file path.
|
|
@param FormId The form need to display.
|
|
|
|
@retval TRUE Exit caller function.
|
|
@retval FALSE Not exit caller function.
|
|
|
|
**/
|
|
BOOLEAN
|
|
UpdatePage(
|
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
|
IN EFI_FORM_ID FormId
|
|
)
|
|
{
|
|
CHAR16 *FileName;
|
|
EFI_STRING_ID StringToken;
|
|
|
|
FileName = NULL;
|
|
|
|
if (FilePath != NULL) {
|
|
FileName = ExtractFileNameFromDevicePath(FilePath);
|
|
}
|
|
if (FileName == NULL) {
|
|
//
|
|
// FileName = NULL has two case:
|
|
// 1. FilePath == NULL, not select file.
|
|
// 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.
|
|
// In these two case, no need to update the form, and exit the caller function.
|
|
//
|
|
return TRUE;
|
|
}
|
|
StringToken = HiiSetString (gSecureBootPrivateData->HiiHandle, 0, FileName, NULL);
|
|
|
|
gSecureBootPrivateData->FileContext->FileName = FileName;
|
|
|
|
OpenFileByDevicePath(
|
|
&FilePath,
|
|
&gSecureBootPrivateData->FileContext->FHandle,
|
|
EFI_FILE_MODE_READ,
|
|
0
|
|
);
|
|
//
|
|
// Create Subtitle op-code for the display string of the option.
|
|
//
|
|
RefreshUpdateData ();
|
|
mStartLabel->Number = FormId;
|
|
|
|
HiiCreateSubTitleOpCode (
|
|
mStartOpCodeHandle,
|
|
StringToken,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
|
|
HiiUpdateForm (
|
|
gSecureBootPrivateData->HiiHandle,
|
|
&gSecureBootConfigFormSetGuid,
|
|
FormId,
|
|
mStartOpCodeHandle, // Label FormId
|
|
mEndOpCodeHandle // LABEL_END
|
|
);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Update the PK form base on the input file path info.
|
|
|
|
@param FilePath Point to the file path.
|
|
|
|
@retval TRUE Exit caller function.
|
|
@retval FALSE Not exit caller function.
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
UpdatePKFromFile (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
|
)
|
|
{
|
|
return UpdatePage(FilePath, FORMID_ENROLL_PK_FORM);
|
|
|
|
}
|
|
|
|
/**
|
|
Update the KEK form base on the input file path info.
|
|
|
|
@param FilePath Point to the file path.
|
|
|
|
@retval TRUE Exit caller function.
|
|
@retval FALSE Not exit caller function.
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
UpdateKEKFromFile (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
|
)
|
|
{
|
|
return UpdatePage(FilePath, FORMID_ENROLL_KEK_FORM);
|
|
}
|
|
|
|
/**
|
|
Update the DB form base on the input file path info.
|
|
|
|
@param FilePath Point to the file path.
|
|
|
|
@retval TRUE Exit caller function.
|
|
@retval FALSE Not exit caller function.
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
UpdateDBFromFile (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
|
)
|
|
{
|
|
return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DB);
|
|
}
|
|
|
|
/**
|
|
Update the DBX form base on the input file path info.
|
|
|
|
@param FilePath Point to the file path.
|
|
|
|
@retval TRUE Exit caller function.
|
|
@retval FALSE Not exit caller function.
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
UpdateDBXFromFile (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
|
)
|
|
{
|
|
return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBX);
|
|
}
|
|
|
|
/**
|
|
Update the DBT form base on the input file path info.
|
|
|
|
@param FilePath Point to the file path.
|
|
|
|
@retval TRUE Exit caller function.
|
|
@retval FALSE Not exit caller function.
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
UpdateDBTFromFile (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
|
)
|
|
{
|
|
return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBT);
|
|
}
|
|
|