]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigFileExplorer.c
SecurityPkg/SecureBootConfigDxe: Fix invalid NV data issue.
[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
ecc722ad 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
762d8ddb 222\r
ecc722ad 223/**\r
762d8ddb 224 Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.\r
ed2992b3
DB
225 The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL\r
226 means not enough memory resource.\r
ecc722ad 227\r
762d8ddb 228 @param DevicePath Device path.\r
ecc722ad 229\r
ed2992b3
DB
230 @retval NULL Not enough memory resourece for AllocateCopyPool.\r
231 @retval Other A new allocated string that represents the file name.\r
ecc722ad 232\r
233**/\r
762d8ddb
DB
234CHAR16 *\r
235ExtractFileNameFromDevicePath (\r
236 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
ecc722ad 237 )\r
238{\r
762d8ddb
DB
239 CHAR16 *String;\r
240 CHAR16 *MatchString;\r
241 CHAR16 *LastMatch;\r
242 CHAR16 *FileName;\r
243 UINTN Length;\r
ecc722ad 244\r
762d8ddb 245 ASSERT(DevicePath != NULL);\r
ecc722ad 246\r
762d8ddb
DB
247 String = DevicePathToStr(DevicePath);\r
248 MatchString = String;\r
249 LastMatch = String;\r
ed2992b3 250 FileName = NULL;\r
ecc722ad 251\r
762d8ddb
DB
252 while(MatchString != NULL){\r
253 LastMatch = MatchString + 1;\r
254 MatchString = StrStr(LastMatch,L"\\");\r
ecc722ad 255 }\r
256\r
762d8ddb
DB
257 Length = StrLen(LastMatch);\r
258 FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);\r
ed2992b3
DB
259 if (FileName != NULL) {\r
260 *(FileName + Length) = 0;\r
261 }\r
ecc722ad 262\r
762d8ddb 263 FreePool(String);\r
20333c6d 264\r
762d8ddb 265 return FileName;\r
ecc722ad 266}\r
267\r
268\r
269/**\r
762d8ddb 270 Update the form base on the selected file.\r
ecc722ad 271\r
762d8ddb
DB
272 @param FilePath Point to the file path.\r
273 @param FormId The form need to display.\r
ecc722ad 274\r
762d8ddb
DB
275 @retval TRUE Exit caller function.\r
276 @retval FALSE Not exit caller function.\r
ecc722ad 277\r
278**/\r
762d8ddb
DB
279BOOLEAN\r
280UpdatePage(\r
281 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
282 IN EFI_FORM_ID FormId\r
ecc722ad 283 )\r
284{\r
762d8ddb
DB
285 CHAR16 *FileName;\r
286 EFI_STRING_ID StringToken;\r
ecc722ad 287\r
ed2992b3
DB
288 FileName = NULL;\r
289\r
290 if (FilePath != NULL) {\r
762d8ddb 291 FileName = ExtractFileNameFromDevicePath(FilePath);\r
ecc722ad 292 }\r
ed2992b3
DB
293 if (FileName == NULL) {\r
294 //\r
295 // FileName = NULL has two case:\r
296 // 1. FilePath == NULL, not select file.\r
297 // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.\r
298 // In these two case, no need to update the form, and exit the caller function.\r
299 //\r
300 return TRUE;\r
301 }\r
302 StringToken = HiiSetString (gSecureBootPrivateData->HiiHandle, 0, FileName, NULL);\r
ecc722ad 303\r
762d8ddb 304 gSecureBootPrivateData->FileContext->FileName = FileName;\r
20333c6d 305\r
762d8ddb
DB
306 OpenFileByDevicePath(\r
307 &FilePath,\r
308 &gSecureBootPrivateData->FileContext->FHandle,\r
309 EFI_FILE_MODE_READ,\r
310 0\r
311 );\r
ecc722ad 312 //\r
762d8ddb 313 // Create Subtitle op-code for the display string of the option.\r
ecc722ad 314 //\r
762d8ddb
DB
315 RefreshUpdateData ();\r
316 mStartLabel->Number = FormId;\r
ecc722ad 317\r
762d8ddb
DB
318 HiiCreateSubTitleOpCode (\r
319 mStartOpCodeHandle,\r
320 StringToken,\r
321 0,\r
322 0,\r
323 0\r
324 );\r
325\r
326 HiiUpdateForm (\r
327 gSecureBootPrivateData->HiiHandle,\r
328 &gSecureBootConfigFormSetGuid,\r
329 FormId,\r
330 mStartOpCodeHandle, // Label FormId\r
331 mEndOpCodeHandle // LABEL_END\r
332 );\r
333\r
334 return TRUE;\r
ecc722ad 335}\r
336\r
337/**\r
762d8ddb 338 Update the PK form base on the input file path info.\r
ecc722ad 339\r
762d8ddb
DB
340 @param FilePath Point to the file path.\r
341\r
342 @retval TRUE Exit caller function.\r
343 @retval FALSE Not exit caller function.\r
ecc722ad 344**/\r
762d8ddb 345BOOLEAN\r
bac308be 346EFIAPI\r
762d8ddb
DB
347UpdatePKFromFile (\r
348 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
ecc722ad 349 )\r
350{\r
762d8ddb 351 return UpdatePage(FilePath, FORMID_ENROLL_PK_FORM);\r
ecc722ad 352\r
ecc722ad 353}\r
354\r
355/**\r
762d8ddb 356 Update the KEK form base on the input file path info.\r
ecc722ad 357\r
762d8ddb 358 @param FilePath Point to the file path.\r
ecc722ad 359\r
762d8ddb
DB
360 @retval TRUE Exit caller function.\r
361 @retval FALSE Not exit caller function.\r
ecc722ad 362**/\r
762d8ddb 363BOOLEAN\r
bac308be 364EFIAPI\r
762d8ddb
DB
365UpdateKEKFromFile (\r
366 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
ecc722ad 367 )\r
368{\r
762d8ddb 369 return UpdatePage(FilePath, FORMID_ENROLL_KEK_FORM);\r
ecc722ad 370}\r
371\r
372/**\r
762d8ddb 373 Update the DB form base on the input file path info.\r
ecc722ad 374\r
762d8ddb 375 @param FilePath Point to the file path.\r
ecc722ad 376\r
762d8ddb
DB
377 @retval TRUE Exit caller function.\r
378 @retval FALSE Not exit caller function.\r
ecc722ad 379**/\r
380BOOLEAN\r
bac308be 381EFIAPI\r
762d8ddb
DB
382UpdateDBFromFile (\r
383 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
ecc722ad 384 )\r
385{\r
762d8ddb
DB
386 return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DB);\r
387}\r
ecc722ad 388\r
762d8ddb
DB
389/**\r
390 Update the DBX form base on the input file path info.\r
ecc722ad 391\r
762d8ddb 392 @param FilePath Point to the file path.\r
ecc722ad 393\r
762d8ddb
DB
394 @retval TRUE Exit caller function.\r
395 @retval FALSE Not exit caller function.\r
396**/\r
397BOOLEAN\r
bac308be 398EFIAPI\r
762d8ddb
DB
399UpdateDBXFromFile (\r
400 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
401 )\r
402{\r
403 return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBX);\r
ecc722ad 404}\r
405\r
406/**\r
762d8ddb 407 Update the DBT form base on the input file path info.\r
ecc722ad 408\r
762d8ddb 409 @param FilePath Point to the file path.\r
ecc722ad 410\r
762d8ddb
DB
411 @retval TRUE Exit caller function.\r
412 @retval FALSE Not exit caller function.\r
ecc722ad 413**/\r
762d8ddb 414BOOLEAN\r
bac308be 415EFIAPI\r
762d8ddb
DB
416UpdateDBTFromFile (\r
417 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
ecc722ad 418 )\r
419{\r
762d8ddb 420 return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBT);\r
ecc722ad 421}\r
762d8ddb 422\r