RdkFile.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. # Copyright (c) 2014-2018, Linaro Limited. All rights reserved.
  3. #
  4. # SPDX-License-Identifier: BSD-2-Clause-Patent
  5. #
  6. */
  7. #include <RdkBootManagerLib.h>
  8. #define MAX_VAR 6
  9. #define ALLOCATE_STRING_MEM(X) AllocateZeroPool((X + 1) * sizeof(CHAR16))
  10. /**
  11. * list_for_each_entry - iterate over list of given type
  12. * @pos: the type * to use as a loop cursor.
  13. * @head: the head for your list.
  14. * @member: the name of the list_struct within the struct.
  15. */
  16. #define LIST_FOR_EACH_ENTRY(Pos, Head, Member) \
  17. for (Pos = BASE_CR((Head)->ForwardLink, typeof(*Pos), Member); \
  18. &Pos->Member != (Head); \
  19. Pos = BASE_CR(Pos->Member.ForwardLink, typeof(*Pos), Member))
  20. /**
  21. * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
  22. * @pos: the type * to use as a loop cursor.
  23. * @n: another type * to use as temporary storage
  24. * @head: the head for your list.
  25. * @member: the name of the list_struct within the struct.
  26. */
  27. #define LIST_FOR_EACH_ENTRY_SAFE(Pos, N, Head, Member) \
  28. for (Pos = BASE_CR((Head)->ForwardLink, typeof(*Pos), Member), \
  29. N = BASE_CR(Pos->Member.ForwardLink, typeof(*Pos), Member); \
  30. &Pos->Member != (Head); \
  31. Pos = N, N = BASE_CR(N->Member.ForwardLink, typeof(*N), Member))
  32. /* ************************** */
  33. typedef struct {
  34. CHAR16 *Name;
  35. LIST_ENTRY List;
  36. } DIR_NODE;
  37. /* ************************** */
  38. STATIC UINT8 VarablesInitialzed = 0;
  39. STATIC CHAR16 *VarResult[MAX_VAR][2];
  40. STATIC
  41. VOID
  42. SaveString (
  43. OUT CHAR16 **Dest,
  44. IN CHAR16 *String1,
  45. IN CHAR16 *String2
  46. )
  47. {
  48. *Dest = ALLOCATE_STRING_MEM (StrLen (String1) + StrLen (String2));
  49. ASSERT (Dest != NULL);
  50. StrCat (*Dest, String1);
  51. StrCat (*Dest, String2);
  52. }
  53. STATIC
  54. EFI_STATUS
  55. LsFiles (
  56. IN CONST CHAR16 *DirPath,
  57. IN CONST CHAR16 *TargetFile,
  58. OUT CHAR16 **Result,
  59. IN LIST_ENTRY *Head
  60. )
  61. {
  62. EFI_STATUS Status;
  63. EFI_FILE_INFO *FileInfo;
  64. EFI_FILE_PROTOCOL *FileHandle;
  65. BOOLEAN NoFile;
  66. CHAR16 *TempPath;
  67. DIR_NODE *Node;
  68. NoFile = FALSE;
  69. TempPath = ALLOCATE_STRING_MEM (StrLen(DirPath) + 1);
  70. StrCat (TempPath, DirPath);
  71. StrCat (TempPath, L"/");
  72. Status = GetFileHandler (&FileHandle, DirPath, EFI_FILE_MODE_READ);
  73. ASSERT_EFI_ERROR (Status);
  74. for ( Status = FileHandleFindFirstFile (FileHandle, &FileInfo);
  75. !EFI_ERROR (Status) && !NoFile;
  76. Status = FileHandleFindNextFile (FileHandle, FileInfo, &NoFile)
  77. ) {
  78. if ( (FileInfo->Attribute & EFI_FILE_DIRECTORY) &&
  79. (StrCmp (FileInfo->FileName, L".") != 0) &&
  80. (StrCmp (FileInfo->FileName, L"..") != 0)) {
  81. Node = AllocateZeroPool (sizeof (DIR_NODE));
  82. //append directory name to the path
  83. SaveString (&Node->Name, TempPath, FileInfo->FileName);
  84. InsertHeadList (Head, &Node->List);
  85. } else if (StrCmp (FileInfo->FileName, TargetFile) == 0) {
  86. //append file to the absolute path
  87. SaveString (Result, TempPath, FileInfo->FileName);
  88. Status = EFI_SUCCESS;
  89. goto Exit;
  90. }
  91. }
  92. Status = EFI_NOT_FOUND;
  93. Exit:
  94. FreePool (TempPath);
  95. return Status;
  96. }
  97. STATIC
  98. VOID
  99. DelDirList (
  100. IN LIST_ENTRY *Head
  101. )
  102. {
  103. DIR_NODE *Node;
  104. DIR_NODE *Temp;
  105. LIST_FOR_EACH_ENTRY_SAFE (Node, Temp, Head, List) {
  106. RemoveEntryList (&Node->List);
  107. FreePool (Node->Name);
  108. FreePool (Node);
  109. }
  110. }
  111. STATIC
  112. EFI_STATUS
  113. FindFileInDir (
  114. IN CONST CHAR16 *DevPath,
  115. IN CONST CHAR16 *TargetFile,
  116. OUT CHAR16 **Result
  117. )
  118. {
  119. UINT8 Current;
  120. UINT8 Next;
  121. DIR_NODE *Temp;
  122. LIST_ENTRY DirList[2];
  123. *Result = NULL;
  124. EFI_STATUS Status = EFI_NOT_FOUND;
  125. InitializeListHead (&DirList[0]);
  126. InitializeListHead (&DirList[1]);
  127. for (Current = Next = 0, Status = LsFiles (\
  128. DevPath, TargetFile, Result, &DirList[Current]);
  129. !IsListEmpty (&DirList[Current]);
  130. Current = Next) {
  131. Next = Current ^ 1;
  132. DelDirList (&DirList[Next]);
  133. LIST_FOR_EACH_ENTRY (Temp, &DirList[Current], List) {
  134. Status = LsFiles (Temp->Name, TargetFile, Result, &DirList[Next]);
  135. if (!EFI_ERROR (Status)) {
  136. DelDirList (&DirList[Current]);
  137. break;
  138. }
  139. }
  140. }
  141. DelDirList (&DirList[Next]);
  142. return Status;
  143. }
  144. STATIC
  145. UINTN
  146. StrSpn (
  147. IN CHAR8 *String,
  148. IN CHAR8 *CharSet
  149. )
  150. {
  151. UINTN Count;
  152. for (Count = 0;
  153. String[Count] && ! (String[Count] == CharSet[0]);
  154. Count++);
  155. return Count;
  156. }
  157. STATIC
  158. EFI_STATUS
  159. InitVarList (
  160. IN CHAR8 *FileData,
  161. IN UINTN FileSize
  162. )
  163. {
  164. UINTN InnerLoopIndex;
  165. UINTN OuterLoopIndex;
  166. UINTN Current;
  167. UINTN Next;
  168. CHAR8 *VarDelimiter[2];
  169. EFI_STATUS Status;
  170. VarDelimiter[0] = "=";
  171. VarDelimiter[1] = "\"";
  172. Status = EFI_SUCCESS;
  173. //Initialize to NULL
  174. for (OuterLoopIndex = 0; OuterLoopIndex < MAX_VAR; OuterLoopIndex++) {
  175. VarResult[OuterLoopIndex][0] = VarResult[OuterLoopIndex][1] = NULL;
  176. }
  177. for (OuterLoopIndex = 0, Next=0;
  178. OuterLoopIndex < MAX_VAR && Next < FileSize;
  179. OuterLoopIndex++) {
  180. for (InnerLoopIndex = 0; InnerLoopIndex < 2; InnerLoopIndex++) {
  181. Current = Next;
  182. Next += StrSpn (&FileData[Next], VarDelimiter[InnerLoopIndex]);
  183. FileData[Next] = '\0';
  184. if (VarResult[OuterLoopIndex][InnerLoopIndex]) {
  185. FreePool (VarResult[OuterLoopIndex][InnerLoopIndex]);
  186. }
  187. VarResult[OuterLoopIndex][InnerLoopIndex] = \
  188. ALLOCATE_STRING_MEM (AsciiStrLen (&FileData[Current]));
  189. AsciiStrToUnicodeStr (&FileData[Current], \
  190. VarResult[OuterLoopIndex][InnerLoopIndex]);
  191. //skip new line
  192. Next += 2;
  193. }
  194. }
  195. return Status;
  196. }
  197. STATIC
  198. EFI_STATUS
  199. InitRdkVariables (
  200. VOID
  201. )
  202. {
  203. EFI_STATUS Status;
  204. UINTN RdkSize;
  205. UINT8 *RdkData;
  206. CHAR16 *Result;
  207. CONST CHAR16 *DevPath;
  208. CONST CHAR16 *RdkFileName;
  209. DevPath = (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileDevicePath);
  210. RdkFileName = (CONST CHAR16 *)FixedPcdGetPtr (PcdRdkConfFileName);
  211. Status = FindFileInDir (DevPath, RdkFileName, &Result);
  212. if (EFI_ERROR (Status)) {
  213. DEBUG ((DEBUG_ERROR, "Failed to find file %s in %s\n", \
  214. RdkFileName, DevPath));
  215. return Status;
  216. }
  217. Status = RdkReadFile ((CONST CHAR16 *)Result, \
  218. (VOID**)&RdkData, &RdkSize);
  219. if (EFI_ERROR (Status)) {
  220. DEBUG ((DEBUG_ERROR, "Failed to read file %s\n", RdkFileName));
  221. return Status;
  222. }
  223. Status = InitVarList ((CHAR8 *)RdkData, RdkSize);
  224. return Status;
  225. }
  226. STATIC
  227. EFI_STATUS
  228. GetVarValue (
  229. IN CONST CHAR16 *Name,
  230. OUT CONST CHAR16 **Value
  231. )
  232. {
  233. UINTN Count;
  234. EFI_STATUS Status;
  235. if (!VarablesInitialzed) {
  236. Status = InitRdkVariables ();
  237. if (EFI_ERROR (Status)) {
  238. return Status;
  239. }
  240. VarablesInitialzed = 1;
  241. }
  242. //Initialize to NULL
  243. *Value = NULL;
  244. for (Count = 0; Count < MAX_VAR; Count++) {
  245. if (VarResult[Count][0] != NULL &&
  246. StrCmp (Name, VarResult[Count][0]) == 0) {
  247. *Value = VarResult[Count][1];
  248. return EFI_SUCCESS;
  249. }
  250. }
  251. return EFI_NOT_FOUND;
  252. }
  253. EFI_STATUS
  254. GetRdkVariable (
  255. IN CONST CHAR16 *Name,
  256. OUT CONST CHAR16 **Value
  257. )
  258. {
  259. EFI_STATUS Status;
  260. Status = GetVarValue (Name, Value);
  261. return Status;
  262. }
  263. EFI_STATUS
  264. RdkReadFile (
  265. IN CONST CHAR16 *Path,
  266. IN OUT VOID **BufferPtr,
  267. OUT UINTN *FileSize
  268. )
  269. {
  270. UINTN BufferSize;
  271. UINT64 SourceFileSize;
  272. VOID *Buffer;
  273. EFI_STATUS Status;
  274. EFI_FILE_HANDLE FileHandle;
  275. Status = GetFileHandler (&FileHandle, Path, EFI_FILE_MODE_READ);
  276. ASSERT_EFI_ERROR (Status);
  277. Buffer = NULL;
  278. // Get the file size
  279. Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
  280. if (EFI_ERROR (Status)) {
  281. goto Exit;
  282. }
  283. Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
  284. if (EFI_ERROR (Status)) {
  285. goto Exit;
  286. }
  287. Status = FileHandle->SetPosition (FileHandle, 0);
  288. if (EFI_ERROR (Status)) {
  289. goto Exit;
  290. }
  291. BufferSize = (UINTN)SourceFileSize;
  292. Buffer = AllocateZeroPool (BufferSize);
  293. if (Buffer == NULL) {
  294. return EFI_OUT_OF_RESOURCES;
  295. }
  296. if (FileSize != NULL) *FileSize = BufferSize;
  297. Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
  298. if (EFI_ERROR (Status) || BufferSize != SourceFileSize) {
  299. FreePool (Buffer);
  300. Buffer = NULL;
  301. Status = EFI_BAD_BUFFER_SIZE;
  302. goto Exit;
  303. }
  304. Exit:
  305. *BufferPtr = Buffer;
  306. return Status;
  307. }
  308. EFI_STATUS
  309. RdkWriteFile (
  310. IN CONST CHAR16 *Path,
  311. IN OUT VOID **BufferPtr,
  312. OUT UINTN *FileSize
  313. )
  314. {
  315. EFI_STATUS Status;
  316. EFI_FILE_HANDLE FileHandle;
  317. if (FileSize == NULL) {
  318. return EFI_INVALID_PARAMETER;
  319. }
  320. Status = GetFileHandler (&FileHandle, Path, \
  321. EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE);
  322. ASSERT_EFI_ERROR (Status);
  323. Status = FileHandle->Write (FileHandle, FileSize, *BufferPtr);
  324. ASSERT_EFI_ERROR (Status);
  325. return Status;
  326. }