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