/** @file | |
The file operation functions for WiFi Connection Manager. | |
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "WifiConnectionMgrFileUtil.h" | |
CHAR16 *mDerPemEncodedSuffix[] = { | |
L".cer", | |
L".der", | |
L".crt", | |
L".pem", | |
NULL | |
}; | |
/** | |
This code checks if the FileSuffix is one of the possible DER/PEM-encoded certificate suffix. | |
@param[in] FileSuffix The suffix of the input certificate file | |
@retval TRUE It's a DER/PEM-encoded certificate. | |
@retval FALSE It's NOT a DER/PEM-encoded certificate. | |
**/ | |
BOOLEAN | |
IsDerPemEncodeCertificate ( | |
IN CONST CHAR16 *FileSuffix | |
) | |
{ | |
UINTN Index; | |
for (Index = 0; mDerPemEncodedSuffix[Index] != NULL; Index++) { | |
if (StrCmp (FileSuffix, mDerPemEncodedSuffix[Index]) == 0) { | |
return TRUE; | |
} | |
} | |
return FALSE; | |
} | |
/** | |
Read file content into BufferPtr, the size of the allocate buffer | |
is *FileSize plus AddtionAllocateSize. | |
@param[in] FileHandle The file to be read. | |
@param[in, out] BufferPtr Pointers to the pointer of allocated buffer. | |
@param[out] FileSize Size of input file | |
@param[in] AddtionAllocateSize Addtion size the buffer need to be allocated. | |
In case the buffer need to contain others besides the file content. | |
@retval EFI_SUCCESS The file was read into the buffer. | |
@retval EFI_INVALID_PARAMETER A parameter was invalid. | |
@retval EFI_OUT_OF_RESOURCES A memory allocation failed. | |
@retval others Unexpected error. | |
**/ | |
EFI_STATUS | |
ReadFileContent ( | |
IN EFI_FILE_HANDLE FileHandle, | |
IN OUT VOID **BufferPtr, | |
OUT UINTN *FileSize, | |
IN UINTN AddtionAllocateSize | |
) | |
{ | |
UINTN BufferSize; | |
UINT64 SourceFileSize; | |
VOID *Buffer; | |
EFI_STATUS Status; | |
if ((FileHandle == NULL) || (FileSize == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Buffer = NULL; | |
// | |
// Get the file size | |
// | |
Status = FileHandle->SetPosition (FileHandle, (UINT64)-1); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
Status = FileHandle->GetPosition (FileHandle, &SourceFileSize); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
Status = FileHandle->SetPosition (FileHandle, 0); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
BufferSize = (UINTN)SourceFileSize + AddtionAllocateSize; | |
Buffer = AllocateZeroPool (BufferSize); | |
if (Buffer == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
BufferSize = (UINTN)SourceFileSize; | |
*FileSize = BufferSize; | |
Status = FileHandle->Read (FileHandle, &BufferSize, Buffer); | |
if (EFI_ERROR (Status) || (BufferSize != *FileSize)) { | |
FreePool (Buffer); | |
Buffer = NULL; | |
Status = EFI_BAD_BUFFER_SIZE; | |
goto ON_EXIT; | |
} | |
ON_EXIT: | |
*BufferPtr = Buffer; | |
return Status; | |
} | |
/** | |
This function converts an input device structure to a Unicode string. | |
@param[in] DevPath A pointer to the device path structure. | |
@return A new allocated Unicode string that represents the device path. | |
**/ | |
CHAR16 * | |
EFIAPI | |
DevicePathToStr ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevPath | |
) | |
{ | |
return ConvertDevicePathToText ( | |
DevPath, | |
FALSE, | |
TRUE | |
); | |
} | |
/** | |
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); | |
if (String == NULL) { | |
return NULL; | |
} | |
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[in] Private The pointer to the global private data structure. | |
@param[in] FilePath Point to the file path. | |
@param[in] FormId The form needs to display. | |
@retval TRUE Exit caller function. | |
@retval FALSE Not exit caller function. | |
**/ | |
BOOLEAN | |
UpdatePage ( | |
IN WIFI_MGR_PRIVATE_DATA *Private, | |
IN EFI_DEVICE_PATH_PROTOCOL *FilePath, | |
IN EFI_FORM_ID FormId | |
) | |
{ | |
CHAR16 *FileName; | |
EFI_STATUS Status; | |
FileName = NULL; | |
if (FilePath != NULL) { | |
FileName = ExtractFileNameFromDevicePath (FilePath); | |
} | |
if (FileName == NULL) { | |
// | |
// FileName = NULL has two cases: | |
// 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; | |
} | |
// | |
// Close the previous file handle before open a new one. | |
// | |
if (Private->FileContext->FHandle != NULL) { | |
Private->FileContext->FHandle->Close (Private->FileContext->FHandle); | |
} | |
Private->FileContext->FHandle = NULL; | |
Status = EfiOpenFileByDevicePath ( | |
&FilePath, | |
&Private->FileContext->FHandle, | |
EFI_FILE_MODE_READ, | |
0 | |
); | |
if (EFI_ERROR (Status)) { | |
if (FormId == FORMID_ENROLL_CERT) { | |
HiiSetString ( | |
Private->RegisteredHandle, | |
STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), | |
L"", | |
NULL | |
); | |
} else if (FormId == FORMID_ENROLL_PRIVATE_KEY) { | |
HiiSetString ( | |
Private->RegisteredHandle, | |
STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), | |
L"", | |
NULL | |
); | |
} | |
} else { | |
if (Private->FileContext->FileName != NULL) { | |
FreePool (Private->FileContext->FileName); | |
Private->FileContext->FileName = NULL; | |
} | |
Private->FileContext->FileName = FileName; | |
if (FormId == FORMID_ENROLL_CERT) { | |
HiiSetString ( | |
Private->RegisteredHandle, | |
STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), | |
FileName, | |
NULL | |
); | |
} else if (FormId == FORMID_ENROLL_PRIVATE_KEY) { | |
HiiSetString ( | |
Private->RegisteredHandle, | |
STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), | |
FileName, | |
NULL | |
); | |
} | |
} | |
return TRUE; | |
} | |
/** | |
Update the CA form base on the input file path info. | |
@param[in] Private The pointer to the global private data structure. | |
@param[in] FilePath Point to the file path. | |
@retval TRUE Exit caller function. | |
@retval FALSE Not exit caller function. | |
**/ | |
BOOLEAN | |
UpdateCAFromFile ( | |
IN WIFI_MGR_PRIVATE_DATA *Private, | |
IN EFI_DEVICE_PATH_PROTOCOL *FilePath | |
) | |
{ | |
return UpdatePage (Private, FilePath, FORMID_ENROLL_CERT); | |
} | |
/** | |
Update the Private Key form base on the input file path info. | |
@param[in] Private The pointer to the global private data structure. | |
@param[in] FilePath Point to the file path. | |
@retval TRUE Exit caller function. | |
@retval FALSE Not exit caller function. | |
**/ | |
BOOLEAN | |
UpdatePrivateKeyFromFile ( | |
IN WIFI_MGR_PRIVATE_DATA *Private, | |
IN EFI_DEVICE_PATH_PROTOCOL *FilePath | |
) | |
{ | |
return UpdatePage (Private, FilePath, FORMID_ENROLL_PRIVATE_KEY); | |
} |