summaryrefslogtreecommitdiff
path: root/Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c')
-rw-r--r--Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c389
1 files changed, 389 insertions, 0 deletions
diff --git a/Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c b/Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c
new file mode 100644
index 0000000000..c398d4b499
--- /dev/null
+++ b/Platform/Comcast/Library/RdkBootManagerLib/RdkFile.c
@@ -0,0 +1,389 @@
+/*
+# Copyright (c) 2014-2018, Linaro Limited. All rights reserved.
+#
+# 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 <RdkBootManagerLib.h>
+
+#define MAX_VAR 6
+
+#define ALLOCATE_STRING_MEM(X) AllocateZeroPool((X + 1) * sizeof(CHAR16))
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define LIST_FOR_EACH_ENTRY(Pos, Head, Member) \
+ for (Pos = BASE_CR((Head)->ForwardLink, typeof(*Pos), Member); \
+ &Pos->Member != (Head); \
+ Pos = BASE_CR(Pos->Member.ForwardLink, typeof(*Pos), Member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define LIST_FOR_EACH_ENTRY_SAFE(Pos, N, Head, Member) \
+ for (Pos = BASE_CR((Head)->ForwardLink, typeof(*Pos), Member), \
+ N = BASE_CR(Pos->Member.ForwardLink, typeof(*Pos), Member); \
+ &Pos->Member != (Head); \
+ Pos = N, N = BASE_CR(N->Member.ForwardLink, typeof(*N), Member))
+
+/* ************************** */
+
+typedef struct {
+ CHAR16 *Name;
+ LIST_ENTRY List;
+} DIR_NODE;
+/* ************************** */
+
+STATIC UINT8 VarablesInitialzed = 0;
+STATIC CHAR16 *VarResult[MAX_VAR][2];
+
+STATIC
+VOID
+SaveString (
+ OUT CHAR16 **Dest,
+ IN CHAR16 *String1,
+ IN CHAR16 *String2
+ )
+{
+ *Dest = ALLOCATE_STRING_MEM (StrLen (String1) + StrLen (String2));
+ ASSERT (Dest != NULL);
+ StrCat (*Dest, String1);
+ StrCat (*Dest, String2);
+}
+
+STATIC
+EFI_STATUS
+LsFiles (
+ IN CONST CHAR16 *DirPath,
+ IN CONST CHAR16 *TargetFile,
+ OUT CHAR16 **Result,
+ IN LIST_ENTRY *Head
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+ EFI_FILE_PROTOCOL *FileHandle;
+ BOOLEAN NoFile;
+ CHAR16 *TempPath;
+ DIR_NODE *Node;
+
+ NoFile = FALSE;
+ TempPath = ALLOCATE_STRING_MEM (StrLen(DirPath) + 1);
+ StrCat (TempPath, DirPath);
+ StrCat (TempPath, L"/");
+
+ Status = GetFileHandler (&FileHandle, DirPath, EFI_FILE_MODE_READ);
+ ASSERT_EFI_ERROR (Status);
+
+ for ( Status = FileHandleFindFirstFile (FileHandle, &FileInfo);
+ !EFI_ERROR (Status) && !NoFile;
+ Status = FileHandleFindNextFile (FileHandle, FileInfo, &NoFile)
+ ) {
+ if ( (FileInfo->Attribute & EFI_FILE_DIRECTORY) &&
+ (StrCmp (FileInfo->FileName, L".") != 0) &&
+ (StrCmp (FileInfo->FileName, L"..") != 0)) {
+ Node = AllocateZeroPool (sizeof (DIR_NODE));
+ //append directory name to the path
+ SaveString (&Node->Name, TempPath, FileInfo->FileName);
+ InsertHeadList (Head, &Node->List);
+ } else if (StrCmp (FileInfo->FileName, TargetFile) == 0) {
+ //append file to the absolute path
+ SaveString (Result, TempPath, FileInfo->FileName);
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ }
+
+ Status = EFI_NOT_FOUND;
+
+Exit:
+ FreePool (TempPath);
+ return Status;
+}
+
+STATIC
+VOID
+DelDirList (
+ IN LIST_ENTRY *Head
+ )
+{
+ DIR_NODE *Node;
+ DIR_NODE *Temp;
+
+ LIST_FOR_EACH_ENTRY_SAFE (Node, Temp, Head, List) {
+ RemoveEntryList (&Node->List);
+ FreePool (Node->Name);
+ FreePool (Node);
+ }
+}
+
+STATIC
+EFI_STATUS
+FindFileInDir (
+ IN CONST CHAR16 *DevPath,
+ IN CONST CHAR16 *TargetFile,
+ OUT CHAR16 **Result
+ )
+{
+ UINT8 Current;
+ UINT8 Next;
+ DIR_NODE *Temp;
+ LIST_ENTRY DirList[2];
+
+ *Result = NULL;
+ EFI_STATUS Status = EFI_NOT_FOUND;
+
+ InitializeListHead (&DirList[0]);
+ InitializeListHead (&DirList[1]);
+
+ for (Current = Next = 0, Status = LsFiles (\
+ DevPath, TargetFile, Result, &DirList[Current]);
+ !IsListEmpty (&DirList[Current]);
+ Current = Next) {
+ Next = Current ^ 1;
+ DelDirList (&DirList[Next]);
+
+ LIST_FOR_EACH_ENTRY (Temp, &DirList[Current], List) {
+ Status = LsFiles (Temp->Name, TargetFile, Result, &DirList[Next]);
+ if (!EFI_ERROR (Status)) {
+ DelDirList (&DirList[Current]);
+ break;
+ }
+ }
+ }
+
+ DelDirList (&DirList[Next]);
+ return Status;
+}
+
+STATIC
+UINTN
+StrSpn (
+ IN CHAR8 *String,
+ IN CHAR8 *CharSet
+ )
+{
+ UINTN Count;
+
+ for (Count = 0;
+ String[Count] && ! (String[Count] == CharSet[0]);
+ Count++);
+ return Count;
+}
+
+STATIC
+EFI_STATUS
+InitVarList (
+ IN CHAR8 *FileData,
+ IN UINTN FileSize
+ )
+{
+ UINTN InnerLoopIndex;
+ UINTN OuterLoopIndex;
+ UINTN Current;
+ UINTN Next;
+ CHAR8 *VarDelimiter[2];
+ EFI_STATUS Status;
+
+ VarDelimiter[0] = "=";
+ VarDelimiter[1] = "\"";
+ Status = EFI_SUCCESS;
+
+ //Initialize to NULL
+ for (OuterLoopIndex = 0; OuterLoopIndex < MAX_VAR; OuterLoopIndex++) {
+ VarResult[OuterLoopIndex][0] = VarResult[OuterLoopIndex][1] = NULL;
+ }
+
+ for (OuterLoopIndex = 0, Next=0;
+ OuterLoopIndex < MAX_VAR && Next < FileSize;
+ OuterLoopIndex++) {
+ for (InnerLoopIndex = 0; InnerLoopIndex < 2; InnerLoopIndex++) {
+ Current = Next;
+ Next += StrSpn (&FileData[Next], VarDelimiter[InnerLoopIndex]);
+ FileData[Next] = '\0';
+ if (VarResult[OuterLoopIndex][InnerLoopIndex]) {
+ FreePool (VarResult[OuterLoopIndex][InnerLoopIndex]);
+ }
+ VarResult[OuterLoopIndex][InnerLoopIndex] = \
+ ALLOCATE_STRING_MEM (AsciiStrLen (&FileData[Current]));
+ AsciiStrToUnicodeStr (&FileData[Current], \
+ VarResult[OuterLoopIndex][InnerLoopIndex]);
+ //skip new line
+ Next += 2;
+ }
+ }
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+InitRdkVariables (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN RdkSize;
+ UINT8 *RdkData;
+ CHAR16 *Result;
+ CONST CHAR16 *DevPath;
+ CONST CHAR16 *RdkFileName;
+
+ DevPath = (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileDevicePath);
+ RdkFileName = (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileName);
+
+ Status = FindFileInDir (DevPath, RdkFileName, &Result);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to find file %s in %s\n", \
+ RdkFileName, DevPath));
+ return Status;
+ }
+
+ Status = RdkReadFile ((CONST CHAR16 *)Result, \
+ (VOID**)&RdkData, &RdkSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to read file %s\n", RdkFileName));
+ return Status;
+ }
+
+ Status = InitVarList ((CHAR8 *)RdkData, RdkSize);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+GetVarValue (
+ IN CONST CHAR16 *Name,
+ OUT CONST CHAR16 **Value
+ )
+{
+ UINTN Count;
+ EFI_STATUS Status;
+
+ if (!VarablesInitialzed) {
+ Status = InitRdkVariables ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VarablesInitialzed = 1;
+ }
+
+ //Initialize to NULL
+ *Value = NULL;
+
+ for (Count = 0; Count < MAX_VAR; Count++) {
+ if (VarResult[Count][0] != NULL &&
+ StrCmp (Name, VarResult[Count][0]) == 0) {
+ *Value = VarResult[Count][1];
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+GetRdkVariable (
+ IN CONST CHAR16 *Name,
+ OUT CONST CHAR16 **Value
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GetVarValue (Name, Value);
+ return Status;
+}
+
+EFI_STATUS
+RdkReadFile (
+ IN CONST CHAR16 *Path,
+ IN OUT VOID **BufferPtr,
+ OUT UINTN *FileSize
+)
+{
+ UINTN BufferSize;
+ UINT64 SourceFileSize;
+ VOID *Buffer;
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE FileHandle;
+
+ Status = GetFileHandler (&FileHandle, Path, EFI_FILE_MODE_READ);
+ ASSERT_EFI_ERROR (Status);
+
+ Buffer = NULL;
+
+ // Get the file size
+ Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Status = FileHandle->SetPosition (FileHandle, 0);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ BufferSize = (UINTN)SourceFileSize;
+ Buffer = AllocateZeroPool (BufferSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (FileSize != NULL) *FileSize = BufferSize;
+
+ Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
+ if (EFI_ERROR (Status) || BufferSize != SourceFileSize) {
+ FreePool (Buffer);
+ Buffer = NULL;
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Exit;
+ }
+
+Exit:
+ *BufferPtr = Buffer;
+ return Status;
+}
+
+EFI_STATUS
+RdkWriteFile (
+ IN CONST CHAR16 *Path,
+ IN OUT VOID **BufferPtr,
+ OUT UINTN *FileSize
+)
+{
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE FileHandle;
+
+ if (FileSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GetFileHandler (&FileHandle, Path, \
+ EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = FileHandle->Write (FileHandle, FileSize, *BufferPtr);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}