1 /** @file
2   Internal file explorer functions for SecureBoot configuration module.
3 
4 Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "SecureBootConfigImpl.h"
10 
11 VOID                  *mStartOpCodeHandle = NULL;
12 VOID                  *mEndOpCodeHandle = NULL;
13 EFI_IFR_GUID_LABEL    *mStartLabel = NULL;
14 EFI_IFR_GUID_LABEL    *mEndLabel = NULL;
15 
16 /**
17   Refresh the global UpdateData structure.
18 
19 **/
20 VOID
RefreshUpdateData(VOID)21 RefreshUpdateData (
22   VOID
23   )
24 {
25   //
26   // Free current updated date
27   //
28   if (mStartOpCodeHandle != NULL) {
29     HiiFreeOpCodeHandle (mStartOpCodeHandle);
30   }
31 
32   //
33   // Create new OpCode Handle
34   //
35   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
36 
37   //
38   // Create Hii Extend Label OpCode as the start opcode
39   //
40   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
41                                          mStartOpCodeHandle,
42                                          &gEfiIfrTianoGuid,
43                                          NULL,
44                                          sizeof (EFI_IFR_GUID_LABEL)
45                                          );
46   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
47 }
48 
49 /**
50   Clean up the dynamic opcode at label and form specified by both LabelId.
51 
52   @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.
53   @param[in] PrivateData     Module private data.
54 
55 **/
56 VOID
CleanUpPage(IN UINT16 LabelId,IN SECUREBOOT_CONFIG_PRIVATE_DATA * PrivateData)57 CleanUpPage (
58   IN UINT16                           LabelId,
59   IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData
60   )
61 {
62   RefreshUpdateData ();
63 
64   //
65   // Remove all op-codes from dynamic page
66   //
67   mStartLabel->Number = LabelId;
68   HiiUpdateForm (
69     PrivateData->HiiHandle,
70     &gSecureBootConfigFormSetGuid,
71     LabelId,
72     mStartOpCodeHandle, // Label LabelId
73     mEndOpCodeHandle    // LABEL_END
74     );
75 }
76 
77 /**
78   Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
79   The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL
80   means not enough memory resource.
81 
82   @param DevicePath       Device path.
83 
84   @retval NULL            Not enough memory resource for AllocateCopyPool.
85   @retval Other           A new allocated string that represents the file name.
86 
87 **/
88 CHAR16 *
ExtractFileNameFromDevicePath(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)89 ExtractFileNameFromDevicePath (
90   IN   EFI_DEVICE_PATH_PROTOCOL *DevicePath
91   )
92 {
93   CHAR16          *String;
94   CHAR16          *MatchString;
95   CHAR16          *LastMatch;
96   CHAR16          *FileName;
97   UINTN           Length;
98 
99   ASSERT(DevicePath != NULL);
100 
101   String = DevicePathToStr(DevicePath);
102   MatchString = String;
103   LastMatch   = String;
104   FileName    = NULL;
105 
106   while(MatchString != NULL){
107     LastMatch   = MatchString + 1;
108     MatchString = StrStr(LastMatch,L"\\");
109   }
110 
111   Length = StrLen(LastMatch);
112   FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
113   if (FileName != NULL) {
114     *(FileName + Length) = 0;
115   }
116 
117   FreePool(String);
118 
119   return FileName;
120 }
121 
122 
123 /**
124   Update  the form base on the selected file.
125 
126   @param FilePath   Point to the file path.
127   @param FormId     The form need to display.
128 
129   @retval TRUE   Exit caller function.
130   @retval FALSE  Not exit caller function.
131 
132 **/
133 BOOLEAN
UpdatePage(IN EFI_DEVICE_PATH_PROTOCOL * FilePath,IN EFI_FORM_ID FormId)134 UpdatePage(
135   IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
136   IN  EFI_FORM_ID               FormId
137   )
138 {
139   CHAR16                *FileName;
140   EFI_STRING_ID         StringToken;
141 
142   FileName = NULL;
143 
144   if (FilePath != NULL) {
145     FileName = ExtractFileNameFromDevicePath(FilePath);
146   }
147   if (FileName == NULL) {
148     //
149     // FileName = NULL has two case:
150     // 1. FilePath == NULL, not select file.
151     // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.
152     // In these two case, no need to update the form, and exit the caller function.
153     //
154     return TRUE;
155   }
156   StringToken =  HiiSetString (gSecureBootPrivateData->HiiHandle, 0, FileName, NULL);
157 
158   gSecureBootPrivateData->FileContext->FileName = FileName;
159 
160   EfiOpenFileByDevicePath (
161     &FilePath,
162     &gSecureBootPrivateData->FileContext->FHandle,
163     EFI_FILE_MODE_READ,
164     0
165     );
166   //
167   // Create Subtitle op-code for the display string of the option.
168   //
169   RefreshUpdateData ();
170   mStartLabel->Number = FormId;
171 
172   HiiCreateSubTitleOpCode (
173     mStartOpCodeHandle,
174     StringToken,
175     0,
176     0,
177     0
178    );
179 
180   HiiUpdateForm (
181     gSecureBootPrivateData->HiiHandle,
182     &gSecureBootConfigFormSetGuid,
183     FormId,
184     mStartOpCodeHandle, // Label FormId
185     mEndOpCodeHandle    // LABEL_END
186     );
187 
188   return TRUE;
189 }
190 
191 /**
192   Update the PK form base on the input file path info.
193 
194   @param FilePath    Point to the file path.
195 
196   @retval TRUE   Exit caller function.
197   @retval FALSE  Not exit caller function.
198 **/
199 BOOLEAN
200 EFIAPI
UpdatePKFromFile(IN EFI_DEVICE_PATH_PROTOCOL * FilePath)201 UpdatePKFromFile (
202   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
203   )
204 {
205   return UpdatePage(FilePath, FORMID_ENROLL_PK_FORM);
206 
207 }
208 
209 /**
210   Update the KEK form base on the input file path info.
211 
212   @param FilePath    Point to the file path.
213 
214   @retval TRUE   Exit caller function.
215   @retval FALSE  Not exit caller function.
216 **/
217 BOOLEAN
218 EFIAPI
UpdateKEKFromFile(IN EFI_DEVICE_PATH_PROTOCOL * FilePath)219 UpdateKEKFromFile (
220   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
221   )
222 {
223   return UpdatePage(FilePath, FORMID_ENROLL_KEK_FORM);
224 }
225 
226 /**
227   Update the DB form base on the input file path info.
228 
229   @param FilePath    Point to the file path.
230 
231   @retval TRUE   Exit caller function.
232   @retval FALSE  Not exit caller function.
233 **/
234 BOOLEAN
235 EFIAPI
UpdateDBFromFile(IN EFI_DEVICE_PATH_PROTOCOL * FilePath)236 UpdateDBFromFile (
237   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
238   )
239 {
240   return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DB);
241 }
242 
243 /**
244   Update the DBX form base on the input file path info.
245 
246   @param FilePath    Point to the file path.
247 
248   @retval TRUE   Exit caller function.
249   @retval FALSE  Not exit caller function.
250 **/
251 BOOLEAN
252 EFIAPI
UpdateDBXFromFile(IN EFI_DEVICE_PATH_PROTOCOL * FilePath)253 UpdateDBXFromFile (
254   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
255   )
256 {
257   return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBX);
258 }
259 
260 /**
261   Update the DBT form base on the input file path info.
262 
263   @param FilePath    Point to the file path.
264 
265   @retval TRUE   Exit caller function.
266   @retval FALSE  Not exit caller function.
267 **/
268 BOOLEAN
269 EFIAPI
UpdateDBTFromFile(IN EFI_DEVICE_PATH_PROTOCOL * FilePath)270 UpdateDBTFromFile (
271   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
272   )
273 {
274   return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBT);
275 }
276 
277