]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigFileExplorer.c
MdeModulePkg/Bds: Support booting from remote file system.
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / SecureBootConfigDxe / SecureBootConfigFileExplorer.c
... / ...
CommitLineData
1/** @file\r
2 Internal file explorer functions for SecureBoot configuration module.\r
3\r
4Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "SecureBootConfigImpl.h"\r
16\r
17VOID *mStartOpCodeHandle = NULL;\r
18VOID *mEndOpCodeHandle = NULL;\r
19EFI_IFR_GUID_LABEL *mStartLabel = NULL;\r
20EFI_IFR_GUID_LABEL *mEndLabel = NULL;\r
21\r
22/**\r
23 Refresh the global UpdateData structure.\r
24\r
25**/\r
26VOID\r
27RefreshUpdateData (\r
28 VOID\r
29 )\r
30{\r
31 //\r
32 // Free current updated date\r
33 //\r
34 if (mStartOpCodeHandle != NULL) {\r
35 HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
36 }\r
37\r
38 //\r
39 // Create new OpCode Handle\r
40 //\r
41 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
42\r
43 //\r
44 // Create Hii Extend Label OpCode as the start opcode\r
45 //\r
46 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
47 mStartOpCodeHandle,\r
48 &gEfiIfrTianoGuid,\r
49 NULL,\r
50 sizeof (EFI_IFR_GUID_LABEL)\r
51 );\r
52 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
53}\r
54\r
55/**\r
56 Clean up the dynamic opcode at label and form specified by both LabelId.\r
57\r
58 @param[in] LabelId It is both the Form ID and Label ID for opcode deletion.\r
59 @param[in] PrivateData Module private data.\r
60\r
61**/\r
62VOID\r
63CleanUpPage (\r
64 IN UINT16 LabelId,\r
65 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
66 )\r
67{\r
68 RefreshUpdateData ();\r
69\r
70 //\r
71 // Remove all op-codes from dynamic page\r
72 //\r
73 mStartLabel->Number = LabelId;\r
74 HiiUpdateForm (\r
75 PrivateData->HiiHandle,\r
76 &gSecureBootConfigFormSetGuid,\r
77 LabelId,\r
78 mStartOpCodeHandle, // Label LabelId\r
79 mEndOpCodeHandle // LABEL_END\r
80 );\r
81}\r
82\r
83/**\r
84 This function will open a file or directory referenced by DevicePath.\r
85\r
86 This function opens a file with the open mode according to the file path. The\r
87 Attributes is valid only for EFI_FILE_MODE_CREATE.\r
88\r
89 @param[in, out] FilePath On input, the device path to the file.\r
90 On output, the remaining device path.\r
91 @param[out] FileHandle Pointer to the file handle.\r
92 @param[in] OpenMode The mode to open the file with.\r
93 @param[in] Attributes The file's file attributes.\r
94\r
95 @retval EFI_SUCCESS The information was set.\r
96 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
97 @retval EFI_UNSUPPORTED Could not open the file path.\r
98 @retval EFI_NOT_FOUND The specified file could not be found on the\r
99 device or the file system could not be found on\r
100 the device.\r
101 @retval EFI_NO_MEDIA The device has no medium.\r
102 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
103 medium is no longer supported.\r
104 @retval EFI_DEVICE_ERROR The device reported an error.\r
105 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
106 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
107 @retval EFI_ACCESS_DENIED The file was opened read only.\r
108 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
109 file.\r
110 @retval EFI_VOLUME_FULL The volume is full.\r
111**/\r
112EFI_STATUS\r
113EFIAPI\r
114OpenFileByDevicePath(\r
115 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
116 OUT EFI_FILE_HANDLE *FileHandle,\r
117 IN UINT64 OpenMode,\r
118 IN UINT64 Attributes\r
119 )\r
120{\r
121 EFI_STATUS Status;\r
122 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
123 EFI_FILE_PROTOCOL *Handle1;\r
124 EFI_FILE_PROTOCOL *Handle2;\r
125 EFI_HANDLE DeviceHandle;\r
126\r
127 if ((FilePath == NULL || FileHandle == NULL)) {\r
128 return EFI_INVALID_PARAMETER;\r
129 }\r
130\r
131 Status = gBS->LocateDevicePath (\r
132 &gEfiSimpleFileSystemProtocolGuid,\r
133 FilePath,\r
134 &DeviceHandle\r
135 );\r
136 if (EFI_ERROR (Status)) {\r
137 return Status;\r
138 }\r
139\r
140 Status = gBS->OpenProtocol(\r
141 DeviceHandle,\r
142 &gEfiSimpleFileSystemProtocolGuid,\r
143 (VOID**)&EfiSimpleFileSystemProtocol,\r
144 gImageHandle,\r
145 NULL,\r
146 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
147 );\r
148 if (EFI_ERROR (Status)) {\r
149 return Status;\r
150 }\r
151\r
152 Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);\r
153 if (EFI_ERROR (Status)) {\r
154 FileHandle = NULL;\r
155 return Status;\r
156 }\r
157\r
158 //\r
159 // go down directories one node at a time.\r
160 //\r
161 while (!IsDevicePathEnd (*FilePath)) {\r
162 //\r
163 // For file system access each node should be a file path component\r
164 //\r
165 if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||\r
166 DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
167 ) {\r
168 FileHandle = NULL;\r
169 return (EFI_INVALID_PARAMETER);\r
170 }\r
171 //\r
172 // Open this file path node\r
173 //\r
174 Handle2 = Handle1;\r
175 Handle1 = NULL;\r
176\r
177 //\r
178 // Try to test opening an existing file\r
179 //\r
180 Status = Handle2->Open (\r
181 Handle2,\r
182 &Handle1,\r
183 ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
184 OpenMode &~EFI_FILE_MODE_CREATE,\r
185 0\r
186 );\r
187\r
188 //\r
189 // see if the error was that it needs to be created\r
190 //\r
191 if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
192 Status = Handle2->Open (\r
193 Handle2,\r
194 &Handle1,\r
195 ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
196 OpenMode,\r
197 Attributes\r
198 );\r
199 }\r
200 //\r
201 // Close the last node\r
202 //\r
203 Handle2->Close (Handle2);\r
204\r
205 if (EFI_ERROR(Status)) {\r
206 return (Status);\r
207 }\r
208\r
209 //\r
210 // Get the next node\r
211 //\r
212 *FilePath = NextDevicePathNode (*FilePath);\r
213 }\r
214\r
215 //\r
216 // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!\r
217 //\r
218 *FileHandle = (VOID*)Handle1;\r
219 return EFI_SUCCESS;\r
220}\r
221\r
222\r
223/**\r
224 Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.\r
225 The caller is responsible for freeing the allocated buffer using FreePool().\r
226\r
227 @param DevicePath Device path.\r
228\r
229 @return A new allocated string that represents the file name.\r
230\r
231**/\r
232CHAR16 *\r
233ExtractFileNameFromDevicePath (\r
234 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
235 )\r
236{\r
237 CHAR16 *String;\r
238 CHAR16 *MatchString;\r
239 CHAR16 *LastMatch;\r
240 CHAR16 *FileName;\r
241 UINTN Length;\r
242\r
243 ASSERT(DevicePath != NULL);\r
244\r
245 String = DevicePathToStr(DevicePath);\r
246 MatchString = String;\r
247 LastMatch = String;\r
248\r
249 while(MatchString != NULL){\r
250 LastMatch = MatchString + 1;\r
251 MatchString = StrStr(LastMatch,L"\\");\r
252 }\r
253\r
254 Length = StrLen(LastMatch);\r
255 FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);\r
256 *(FileName + Length) = 0;\r
257\r
258 FreePool(String);\r
259\r
260 return FileName;\r
261}\r
262\r
263\r
264/**\r
265 Update the form base on the selected file.\r
266\r
267 @param FilePath Point to the file path.\r
268 @param FormId The form need to display.\r
269\r
270 @retval TRUE Exit caller function.\r
271 @retval FALSE Not exit caller function.\r
272\r
273**/\r
274BOOLEAN\r
275UpdatePage(\r
276 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
277 IN EFI_FORM_ID FormId\r
278 )\r
279{\r
280 CHAR16 *FileName;\r
281 EFI_STRING_ID StringToken;\r
282\r
283 if (FilePath != NULL){\r
284 FileName = ExtractFileNameFromDevicePath(FilePath);\r
285 StringToken = HiiSetString (gSecureBootPrivateData->HiiHandle, 0, FileName, NULL);\r
286 } else {\r
287 FileName = HiiGetString (gSecureBootPrivateData->HiiHandle, STRING_TOKEN (STR_NULL), NULL);\r
288 ASSERT (FileName != NULL);\r
289 StringToken = HiiSetString (gSecureBootPrivateData->HiiHandle, 0, FileName, NULL);\r
290 }\r
291\r
292 gSecureBootPrivateData->FileContext->FileName = FileName;\r
293\r
294 OpenFileByDevicePath(\r
295 &FilePath,\r
296 &gSecureBootPrivateData->FileContext->FHandle,\r
297 EFI_FILE_MODE_READ,\r
298 0\r
299 );\r
300 //\r
301 // Create Subtitle op-code for the display string of the option.\r
302 //\r
303 RefreshUpdateData ();\r
304 mStartLabel->Number = FormId;\r
305\r
306 HiiCreateSubTitleOpCode (\r
307 mStartOpCodeHandle,\r
308 StringToken,\r
309 0,\r
310 0,\r
311 0\r
312 );\r
313\r
314 HiiUpdateForm (\r
315 gSecureBootPrivateData->HiiHandle,\r
316 &gSecureBootConfigFormSetGuid,\r
317 FormId,\r
318 mStartOpCodeHandle, // Label FormId\r
319 mEndOpCodeHandle // LABEL_END\r
320 );\r
321\r
322 return TRUE;\r
323}\r
324\r
325/**\r
326 Update the PK form base on the input file path info.\r
327\r
328 @param FilePath Point to the file path.\r
329\r
330 @retval TRUE Exit caller function.\r
331 @retval FALSE Not exit caller function.\r
332**/\r
333BOOLEAN\r
334UpdatePKFromFile (\r
335 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
336 )\r
337{\r
338 return UpdatePage(FilePath, FORMID_ENROLL_PK_FORM);\r
339\r
340}\r
341\r
342/**\r
343 Update the KEK form base on the input file path info.\r
344\r
345 @param FilePath Point to the file path.\r
346\r
347 @retval TRUE Exit caller function.\r
348 @retval FALSE Not exit caller function.\r
349**/\r
350BOOLEAN\r
351UpdateKEKFromFile (\r
352 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
353 )\r
354{\r
355 return UpdatePage(FilePath, FORMID_ENROLL_KEK_FORM);\r
356}\r
357\r
358/**\r
359 Update the DB form base on the input file path info.\r
360\r
361 @param FilePath Point to the file path.\r
362\r
363 @retval TRUE Exit caller function.\r
364 @retval FALSE Not exit caller function.\r
365**/\r
366BOOLEAN\r
367UpdateDBFromFile (\r
368 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
369 )\r
370{\r
371 return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DB);\r
372}\r
373\r
374/**\r
375 Update the DBX form base on the input file path info.\r
376\r
377 @param FilePath Point to the file path.\r
378\r
379 @retval TRUE Exit caller function.\r
380 @retval FALSE Not exit caller function.\r
381**/\r
382BOOLEAN\r
383UpdateDBXFromFile (\r
384 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
385 )\r
386{\r
387 return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBX);\r
388}\r
389\r
390/**\r
391 Update the DBT form base on the input file path info.\r
392\r
393 @param FilePath Point to the file path.\r
394\r
395 @retval TRUE Exit caller function.\r
396 @retval FALSE Not exit caller function.\r
397**/\r
398BOOLEAN\r
399UpdateDBTFromFile (\r
400 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
401 )\r
402{\r
403 return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBT);\r
404}\r
405\r