SecurityPkg: Fix assert when setting key from eMMC/SD/USB
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / SecureBootConfigDxe / SecureBootConfigFileExplorer.c
CommitLineData
ecc722ad 1/** @file\r
2 Internal file explorer functions for SecureBoot configuration module.\r
3\r
762d8ddb 4Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>\r
ecc722ad 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
ecc722ad 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
762d8ddb 23 Refresh the global UpdateData structure.\r
ecc722ad 24\r
25**/\r
762d8ddb
DB
26VOID\r
27RefreshUpdateData (\r
28 VOID\r
ecc722ad 29 )\r
30{\r
ecc722ad 31 //\r
762d8ddb 32 // Free current updated date\r
ecc722ad 33 //\r
762d8ddb
DB
34 if (mStartOpCodeHandle != NULL) {\r
35 HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
ecc722ad 36 }\r
ecc722ad 37\r
ecc722ad 38 //\r
762d8ddb 39 // Create new OpCode Handle\r
ecc722ad 40 //\r
762d8ddb 41 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
ecc722ad 42\r
43 //\r
762d8ddb 44 // Create Hii Extend Label OpCode as the start opcode\r
ecc722ad 45 //\r
762d8ddb
DB
46 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
47 mStartOpCodeHandle,\r
48 &gEfiIfrTianoGuid,\r
49 NULL,\r
50 sizeof (EFI_IFR_GUID_LABEL)\r
ecc722ad 51 );\r
762d8ddb 52 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
ecc722ad 53}\r
54\r
55/**\r
762d8ddb 56 Clean up the dynamic opcode at label and form specified by both LabelId.\r
ecc722ad 57\r
762d8ddb
DB
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
20333c6d 60\r
ecc722ad 61**/\r
62VOID\r
762d8ddb
DB
63CleanUpPage (\r
64 IN UINT16 LabelId,\r
65 IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData\r
ecc722ad 66 )\r
67{\r
762d8ddb 68 RefreshUpdateData ();\r
ecc722ad 69\r
70 //\r
762d8ddb 71 // Remove all op-codes from dynamic page\r
ecc722ad 72 //\r
762d8ddb
DB
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
ecc722ad 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
20333c6d 89 @param[in, out] FilePath On input, the device path to the file.\r
ecc722ad 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
20333c6d 125 EFI_HANDLE DeviceHandle;\r
79b10d4c
RB
126 CHAR16 *PathName;\r
127 UINTN PathLength;\r
ecc722ad 128\r
129 if ((FilePath == NULL || FileHandle == NULL)) {\r
130 return EFI_INVALID_PARAMETER;\r
131 }\r
132\r
133 Status = gBS->LocateDevicePath (\r
134 &gEfiSimpleFileSystemProtocolGuid,\r
135 FilePath,\r
136 &DeviceHandle\r
137 );\r
138 if (EFI_ERROR (Status)) {\r
139 return Status;\r
140 }\r
141\r
142 Status = gBS->OpenProtocol(\r
143 DeviceHandle,\r
144 &gEfiSimpleFileSystemProtocolGuid,\r
145 (VOID**)&EfiSimpleFileSystemProtocol,\r
146 gImageHandle,\r
147 NULL,\r
148 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
149 );\r
150 if (EFI_ERROR (Status)) {\r
151 return Status;\r
152 }\r
153\r
154 Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);\r
155 if (EFI_ERROR (Status)) {\r
156 FileHandle = NULL;\r
157 return Status;\r
158 }\r
159\r
160 //\r
161 // go down directories one node at a time.\r
162 //\r
163 while (!IsDevicePathEnd (*FilePath)) {\r
164 //\r
165 // For file system access each node should be a file path component\r
166 //\r
167 if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||\r
168 DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
169 ) {\r
170 FileHandle = NULL;\r
171 return (EFI_INVALID_PARAMETER);\r
172 }\r
173 //\r
174 // Open this file path node\r
175 //\r
176 Handle2 = Handle1;\r
177 Handle1 = NULL;\r
79b10d4c
RB
178 PathLength = DevicePathNodeLength (*FilePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
179 PathName = AllocateCopyPool (PathLength, ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName);\r
180 if (PathName == NULL) {\r
181 return EFI_OUT_OF_RESOURCES;\r
182 }\r
ecc722ad 183\r
184 //\r
185 // Try to test opening an existing file\r
186 //\r
187 Status = Handle2->Open (\r
188 Handle2,\r
189 &Handle1,\r
79b10d4c 190 PathName,\r
ecc722ad 191 OpenMode &~EFI_FILE_MODE_CREATE,\r
192 0\r
193 );\r
194\r
195 //\r
196 // see if the error was that it needs to be created\r
197 //\r
198 if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
199 Status = Handle2->Open (\r
200 Handle2,\r
201 &Handle1,\r
79b10d4c 202 PathName,\r
ecc722ad 203 OpenMode,\r
204 Attributes\r
205 );\r
206 }\r
207 //\r
208 // Close the last node\r
209 //\r
210 Handle2->Close (Handle2);\r
211\r
79b10d4c
RB
212 FreePool (PathName);\r
213\r
ecc722ad 214 if (EFI_ERROR(Status)) {\r
215 return (Status);\r
216 }\r
217\r
218 //\r
219 // Get the next node\r
220 //\r
221 *FilePath = NextDevicePathNode (*FilePath);\r
222 }\r
223\r
224 //\r
225 // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!\r
226 //\r
227 *FileHandle = (VOID*)Handle1;\r
228 return EFI_SUCCESS;\r
229}\r
230\r
762d8ddb 231\r
ecc722ad 232/**\r
762d8ddb 233 Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.\r
ed2992b3
DB
234 The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL\r
235 means not enough memory resource.\r
ecc722ad 236\r
762d8ddb 237 @param DevicePath Device path.\r
ecc722ad 238\r
ed2992b3
DB
239 @retval NULL Not enough memory resourece for AllocateCopyPool.\r
240 @retval Other A new allocated string that represents the file name.\r
ecc722ad 241\r
242**/\r
762d8ddb
DB
243CHAR16 *\r
244ExtractFileNameFromDevicePath (\r
245 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
ecc722ad 246 )\r
247{\r
762d8ddb
DB
248 CHAR16 *String;\r
249 CHAR16 *MatchString;\r
250 CHAR16 *LastMatch;\r
251 CHAR16 *FileName;\r
252 UINTN Length;\r
ecc722ad 253\r
762d8ddb 254 ASSERT(DevicePath != NULL);\r
ecc722ad 255\r
762d8ddb
DB
256 String = DevicePathToStr(DevicePath);\r
257 MatchString = String;\r
258 LastMatch = String;\r
ed2992b3 259 FileName = NULL;\r
ecc722ad 260\r
762d8ddb
DB
261 while(MatchString != NULL){\r
262 LastMatch = MatchString + 1;\r
263 MatchString = StrStr(LastMatch,L"\\");\r
ecc722ad 264 }\r
265\r
762d8ddb
DB
266 Length = StrLen(LastMatch);\r
267 FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);\r
ed2992b3
DB
268 if (FileName != NULL) {\r
269 *(FileName + Length) = 0;\r
270 }\r
ecc722ad 271\r
762d8ddb 272 FreePool(String);\r
20333c6d 273\r
762d8ddb 274 return FileName;\r
ecc722ad 275}\r
276\r
277\r
278/**\r
762d8ddb 279 Update the form base on the selected file.\r
ecc722ad 280\r
762d8ddb
DB
281 @param FilePath Point to the file path.\r
282 @param FormId The form need to display.\r
ecc722ad 283\r
762d8ddb
DB
284 @retval TRUE Exit caller function.\r
285 @retval FALSE Not exit caller function.\r
ecc722ad 286\r
287**/\r
762d8ddb
DB
288BOOLEAN\r
289UpdatePage(\r
290 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
291 IN EFI_FORM_ID FormId\r
ecc722ad 292 )\r
293{\r
762d8ddb
DB
294 CHAR16 *FileName;\r
295 EFI_STRING_ID StringToken;\r
ecc722ad 296\r
ed2992b3
DB
297 FileName = NULL;\r
298\r
299 if (FilePath != NULL) {\r
762d8ddb 300 FileName = ExtractFileNameFromDevicePath(FilePath);\r
ecc722ad 301 }\r
ed2992b3
DB
302 if (FileName == NULL) {\r
303 //\r
304 // FileName = NULL has two case:\r
305 // 1. FilePath == NULL, not select file.\r
306 // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.\r
307 // In these two case, no need to update the form, and exit the caller function.\r
308 //\r
309 return TRUE;\r
310 }\r
311 StringToken = HiiSetString (gSecureBootPrivateData->HiiHandle, 0, FileName, NULL);\r
ecc722ad 312\r
762d8ddb 313 gSecureBootPrivateData->FileContext->FileName = FileName;\r
20333c6d 314\r
762d8ddb
DB
315 OpenFileByDevicePath(\r
316 &FilePath,\r
317 &gSecureBootPrivateData->FileContext->FHandle,\r
318 EFI_FILE_MODE_READ,\r
319 0\r
320 );\r
ecc722ad 321 //\r
762d8ddb 322 // Create Subtitle op-code for the display string of the option.\r
ecc722ad 323 //\r
762d8ddb
DB
324 RefreshUpdateData ();\r
325 mStartLabel->Number = FormId;\r
ecc722ad 326\r
762d8ddb
DB
327 HiiCreateSubTitleOpCode (\r
328 mStartOpCodeHandle,\r
329 StringToken,\r
330 0,\r
331 0,\r
332 0\r
333 );\r
334\r
335 HiiUpdateForm (\r
336 gSecureBootPrivateData->HiiHandle,\r
337 &gSecureBootConfigFormSetGuid,\r
338 FormId,\r
339 mStartOpCodeHandle, // Label FormId\r
340 mEndOpCodeHandle // LABEL_END\r
341 );\r
342\r
343 return TRUE;\r
ecc722ad 344}\r
345\r
346/**\r
762d8ddb 347 Update the PK form base on the input file path info.\r
ecc722ad 348\r
762d8ddb
DB
349 @param FilePath Point to the file path.\r
350\r
351 @retval TRUE Exit caller function.\r
352 @retval FALSE Not exit caller function.\r
ecc722ad 353**/\r
762d8ddb 354BOOLEAN\r
bac308be 355EFIAPI\r
762d8ddb
DB
356UpdatePKFromFile (\r
357 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
ecc722ad 358 )\r
359{\r
762d8ddb 360 return UpdatePage(FilePath, FORMID_ENROLL_PK_FORM);\r
ecc722ad 361\r
ecc722ad 362}\r
363\r
364/**\r
762d8ddb 365 Update the KEK form base on the input file path info.\r
ecc722ad 366\r
762d8ddb 367 @param FilePath Point to the file path.\r
ecc722ad 368\r
762d8ddb
DB
369 @retval TRUE Exit caller function.\r
370 @retval FALSE Not exit caller function.\r
ecc722ad 371**/\r
762d8ddb 372BOOLEAN\r
bac308be 373EFIAPI\r
762d8ddb
DB
374UpdateKEKFromFile (\r
375 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
ecc722ad 376 )\r
377{\r
762d8ddb 378 return UpdatePage(FilePath, FORMID_ENROLL_KEK_FORM);\r
ecc722ad 379}\r
380\r
381/**\r
762d8ddb 382 Update the DB form base on the input file path info.\r
ecc722ad 383\r
762d8ddb 384 @param FilePath Point to the file path.\r
ecc722ad 385\r
762d8ddb
DB
386 @retval TRUE Exit caller function.\r
387 @retval FALSE Not exit caller function.\r
ecc722ad 388**/\r
389BOOLEAN\r
bac308be 390EFIAPI\r
762d8ddb
DB
391UpdateDBFromFile (\r
392 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
ecc722ad 393 )\r
394{\r
762d8ddb
DB
395 return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DB);\r
396}\r
ecc722ad 397\r
762d8ddb
DB
398/**\r
399 Update the DBX form base on the input file path info.\r
ecc722ad 400\r
762d8ddb 401 @param FilePath Point to the file path.\r
ecc722ad 402\r
762d8ddb
DB
403 @retval TRUE Exit caller function.\r
404 @retval FALSE Not exit caller function.\r
405**/\r
406BOOLEAN\r
bac308be 407EFIAPI\r
762d8ddb
DB
408UpdateDBXFromFile (\r
409 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
410 )\r
411{\r
412 return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBX);\r
ecc722ad 413}\r
414\r
415/**\r
762d8ddb 416 Update the DBT form base on the input file path info.\r
ecc722ad 417\r
762d8ddb 418 @param FilePath Point to the file path.\r
ecc722ad 419\r
762d8ddb
DB
420 @retval TRUE Exit caller function.\r
421 @retval FALSE Not exit caller function.\r
ecc722ad 422**/\r
762d8ddb 423BOOLEAN\r
bac308be 424EFIAPI\r
762d8ddb
DB
425UpdateDBTFromFile (\r
426 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
ecc722ad 427 )\r
428{\r
762d8ddb 429 return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBT);\r
ecc722ad 430}\r
762d8ddb 431\r