NetworkPkg: Convert files to CRLF line ending
[mirror_edk2.git] / NetworkPkg / TlsAuthConfigDxe / TlsAuthConfigImpl.c
1 /** @file\r
2   The Miscellaneous Routines for TlsAuthConfigDxe driver.\r
3 \r
4 Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
5 \r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution.  The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10 \r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 \r
14 **/\r
15 \r
16 #include "TlsAuthConfigImpl.h"\r
17 \r
18 VOID                    *mStartOpCodeHandle = NULL;\r
19 VOID                    *mEndOpCodeHandle   = NULL;\r
20 EFI_IFR_GUID_LABEL      *mStartLabel        = NULL;\r
21 EFI_IFR_GUID_LABEL      *mEndLabel          = NULL;\r
22 \r
23 \r
24 CHAR16                  mTlsAuthConfigStorageName[] = L"TLS_AUTH_CONFIG_IFR_NVDATA";\r
25 \r
26 TLS_AUTH_CONFIG_PRIVATE_DATA      *mTlsAuthPrivateData = NULL;\r
27 \r
28 HII_VENDOR_DEVICE_PATH  mTlsAuthConfigHiiVendorDevicePath = {\r
29   {\r
30     {\r
31       HARDWARE_DEVICE_PATH,\r
32       HW_VENDOR_DP,\r
33       {\r
34         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
35         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
36       }\r
37     },\r
38     TLS_AUTH_CONFIG_GUID\r
39   },\r
40   {\r
41     END_DEVICE_PATH_TYPE,\r
42     END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
43     {\r
44       (UINT8) (END_DEVICE_PATH_LENGTH),\r
45       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
46     }\r
47   }\r
48 };\r
49 \r
50 //\r
51 // Possible DER-encoded certificate file suffixes, end with NULL pointer.\r
52 //\r
53 CHAR16* mDerPemEncodedSuffix[] = {\r
54   L".cer",\r
55   L".der",\r
56   L".crt",\r
57   L".pem",\r
58   NULL\r
59 };\r
60 \r
61 /**\r
62   This code checks if the FileSuffix is one of the possible DER/PEM-encoded certificate suffix.\r
63 \r
64   @param[in] FileSuffix            The suffix of the input certificate file\r
65 \r
66   @retval    TRUE           It's a DER/PEM-encoded certificate.\r
67   @retval    FALSE          It's NOT a DER/PEM-encoded certificate.\r
68 \r
69 **/\r
70 BOOLEAN\r
71 IsDerPemEncodeCertificate (\r
72   IN CONST CHAR16         *FileSuffix\r
73 )\r
74 {\r
75   UINTN     Index;\r
76   for (Index = 0; mDerPemEncodedSuffix[Index] != NULL; Index++) {\r
77     if (StrCmp (FileSuffix, mDerPemEncodedSuffix[Index]) == 0) {\r
78       return TRUE;\r
79     }\r
80   }\r
81   return FALSE;\r
82 }\r
83 \r
84 /**\r
85   Worker function that prints an EFI_GUID into specified Buffer.\r
86 \r
87   @param[in]     Guid          Pointer to GUID to print.\r
88   @param[in]     Buffer        Buffer to print Guid into.\r
89   @param[in]     BufferSize    Size of Buffer.\r
90 \r
91   @retval    Number of characters printed.\r
92 \r
93 **/\r
94 UINTN\r
95 GuidToString (\r
96   IN  EFI_GUID  *Guid,\r
97   IN  CHAR16    *Buffer,\r
98   IN  UINTN     BufferSize\r
99   )\r
100 {\r
101   return UnicodeSPrint (\r
102            Buffer,\r
103            BufferSize,\r
104            L"%g",\r
105            Guid\r
106            );\r
107 }\r
108 \r
109 /**\r
110   List all cert in specified database by GUID in the page\r
111   for user to select and delete as needed.\r
112 \r
113   @param[in]    PrivateData         Module's private data.\r
114   @param[in]    VariableName        The variable name of the vendor's signature database.\r
115   @param[in]    VendorGuid          A unique identifier for the vendor.\r
116   @param[in]    LabelNumber         Label number to insert opcodes.\r
117   @param[in]    FormId              Form ID of current page.\r
118   @param[in]    QuestionIdBase      Base question id of the signature list.\r
119 \r
120   @retval   EFI_SUCCESS             Success to update the signature list page\r
121   @retval   EFI_OUT_OF_RESOURCES    Unable to allocate required resources.\r
122 \r
123 **/\r
124 EFI_STATUS\r
125 UpdateDeletePage (\r
126   IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,\r
127   IN CHAR16                           *VariableName,\r
128   IN EFI_GUID                         *VendorGuid,\r
129   IN UINT16                           LabelNumber,\r
130   IN EFI_FORM_ID                      FormId,\r
131   IN EFI_QUESTION_ID                  QuestionIdBase\r
132   )\r
133 {\r
134   EFI_STATUS                  Status;\r
135   UINT32                      Index;\r
136   UINTN                       CertCount;\r
137   UINTN                       GuidIndex;\r
138   VOID                        *StartOpCodeHandle;\r
139   VOID                        *EndOpCodeHandle;\r
140   EFI_IFR_GUID_LABEL          *StartLabel;\r
141   EFI_IFR_GUID_LABEL          *EndLabel;\r
142   UINTN                       DataSize;\r
143   UINT8                       *Data;\r
144   EFI_SIGNATURE_LIST          *CertList;\r
145   EFI_SIGNATURE_DATA          *Cert;\r
146   UINT32                      ItemDataSize;\r
147   CHAR16                      *GuidStr;\r
148   EFI_STRING_ID               GuidID;\r
149   EFI_STRING_ID               Help;\r
150 \r
151   Data     = NULL;\r
152   CertList = NULL;\r
153   Cert     = NULL;\r
154   GuidStr  = NULL;\r
155   StartOpCodeHandle = NULL;\r
156   EndOpCodeHandle   = NULL;\r
157 \r
158   //\r
159   // Initialize the container for dynamic opcodes.\r
160   //\r
161   StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
162   if (StartOpCodeHandle == NULL) {\r
163     Status = EFI_OUT_OF_RESOURCES;\r
164     goto ON_EXIT;\r
165   }\r
166 \r
167   EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
168   if (EndOpCodeHandle == NULL) {\r
169     Status = EFI_OUT_OF_RESOURCES;\r
170     goto ON_EXIT;\r
171   }\r
172 \r
173   //\r
174   // Create Hii Extend Label OpCode.\r
175   //\r
176   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
177                                         StartOpCodeHandle,\r
178                                         &gEfiIfrTianoGuid,\r
179                                         NULL,\r
180                                         sizeof (EFI_IFR_GUID_LABEL)\r
181                                         );\r
182   StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
183   StartLabel->Number        = LabelNumber;\r
184 \r
185   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
186                                       EndOpCodeHandle,\r
187                                       &gEfiIfrTianoGuid,\r
188                                       NULL,\r
189                                       sizeof (EFI_IFR_GUID_LABEL)\r
190                                       );\r
191   EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
192   EndLabel->Number        = LABEL_END;\r
193 \r
194   //\r
195   // Read Variable.\r
196   //\r
197   DataSize = 0;\r
198   Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
199   if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
200     goto ON_EXIT;\r
201   }\r
202 \r
203   Data = (UINT8 *) AllocateZeroPool (DataSize);\r
204   if (Data == NULL) {\r
205     Status = EFI_OUT_OF_RESOURCES;\r
206     goto ON_EXIT;\r
207   }\r
208 \r
209   Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
210   if (EFI_ERROR (Status)) {\r
211     goto ON_EXIT;\r
212   }\r
213 \r
214   GuidStr = AllocateZeroPool (100);\r
215   if (GuidStr == NULL) {\r
216     Status = EFI_OUT_OF_RESOURCES;\r
217     goto ON_EXIT;\r
218   }\r
219 \r
220   //\r
221   // Enumerate all data.\r
222   //\r
223   ItemDataSize = (UINT32) DataSize;\r
224   CertList = (EFI_SIGNATURE_LIST *) Data;\r
225   GuidIndex = 0;\r
226 \r
227   while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
228 \r
229     if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
230       Help = STRING_TOKEN (STR_CERT_TYPE_PCKS_GUID);\r
231     } else {\r
232       //\r
233       // The signature type is not supported in current implementation.\r
234       //\r
235       ItemDataSize -= CertList->SignatureListSize;\r
236       CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
237       continue;\r
238     }\r
239 \r
240     CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
241     for (Index = 0; Index < CertCount; Index++) {\r
242       Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList\r
243                                               + sizeof (EFI_SIGNATURE_LIST)\r
244                                               + CertList->SignatureHeaderSize\r
245                                               + Index * CertList->SignatureSize);\r
246       //\r
247       // Display GUID and help\r
248       //\r
249       GuidToString (&Cert->SignatureOwner, GuidStr, 100);\r
250       GuidID  = HiiSetString (Private->RegisteredHandle, 0, GuidStr, NULL);\r
251       HiiCreateCheckBoxOpCode (\r
252         StartOpCodeHandle,\r
253         (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),\r
254         0,\r
255         0,\r
256         GuidID,\r
257         Help,\r
258         EFI_IFR_FLAG_CALLBACK,\r
259         0,\r
260         NULL\r
261         );\r
262     }\r
263 \r
264     ItemDataSize -= CertList->SignatureListSize;\r
265     CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
266   }\r
267 \r
268 ON_EXIT:\r
269   HiiUpdateForm (\r
270     Private->RegisteredHandle,\r
271     &gTlsAuthConfigGuid,\r
272     FormId,\r
273     StartOpCodeHandle,\r
274     EndOpCodeHandle\r
275     );\r
276 \r
277   if (StartOpCodeHandle != NULL) {\r
278     HiiFreeOpCodeHandle (StartOpCodeHandle);\r
279   }\r
280 \r
281   if (EndOpCodeHandle != NULL) {\r
282     HiiFreeOpCodeHandle (EndOpCodeHandle);\r
283   }\r
284 \r
285   if (Data != NULL) {\r
286     FreePool (Data);\r
287   }\r
288 \r
289   if (GuidStr != NULL) {\r
290     FreePool (GuidStr);\r
291   }\r
292 \r
293   return EFI_SUCCESS;\r
294 }\r
295 \r
296 /**\r
297   Delete one entry from cert database.\r
298 \r
299   @param[in]    PrivateData         Module's private data.\r
300   @param[in]    VariableName        The variable name of the database.\r
301   @param[in]    VendorGuid          A unique identifier for the vendor.\r
302   @param[in]    LabelNumber         Label number to insert opcodes.\r
303   @param[in]    FormId              Form ID of current page.\r
304   @param[in]    QuestionIdBase      Base question id of the cert list.\r
305   @param[in]    DeleteIndex         Cert index to delete.\r
306 \r
307   @retval   EFI_SUCCESS             Delete siganture successfully.\r
308   @retval   EFI_NOT_FOUND           Can't find the signature item,\r
309   @retval   EFI_OUT_OF_RESOURCES    Could not allocate needed resources.\r
310 **/\r
311 EFI_STATUS\r
312 DeleteCert (\r
313   IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,\r
314   IN CHAR16                           *VariableName,\r
315   IN EFI_GUID                         *VendorGuid,\r
316   IN UINT16                           LabelNumber,\r
317   IN EFI_FORM_ID                      FormId,\r
318   IN EFI_QUESTION_ID                  QuestionIdBase,\r
319   IN UINTN                            DeleteIndex\r
320   )\r
321 {\r
322   EFI_STATUS                  Status;\r
323   UINTN                       DataSize;\r
324   UINT8                       *Data;\r
325   UINT8                       *OldData;\r
326   UINT32                      Attr;\r
327   UINT32                      Index;\r
328   EFI_SIGNATURE_LIST          *CertList;\r
329   EFI_SIGNATURE_LIST          *NewCertList;\r
330   EFI_SIGNATURE_DATA          *Cert;\r
331   UINTN                       CertCount;\r
332   UINT32                      Offset;\r
333   BOOLEAN                     IsItemFound;\r
334   UINT32                      ItemDataSize;\r
335   UINTN                       GuidIndex;\r
336 \r
337   Data            = NULL;\r
338   OldData         = NULL;\r
339   CertList        = NULL;\r
340   Cert            = NULL;\r
341   Attr            = 0;\r
342 \r
343   //\r
344   // Get original signature list data.\r
345   //\r
346   DataSize = 0;\r
347   Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
348   if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
349     goto ON_EXIT;\r
350   }\r
351 \r
352   OldData = (UINT8 *) AllocateZeroPool (DataSize);\r
353   if (OldData == NULL) {\r
354     Status = EFI_OUT_OF_RESOURCES;\r
355     goto ON_EXIT;\r
356   }\r
357 \r
358   Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);\r
359   if (EFI_ERROR(Status)) {\r
360     goto ON_EXIT;\r
361   }\r
362 \r
363   //\r
364   // Allocate space for new variable.\r
365   //\r
366   Data = (UINT8*) AllocateZeroPool (DataSize);\r
367   if (Data == NULL) {\r
368     Status  =  EFI_OUT_OF_RESOURCES;\r
369     goto ON_EXIT;\r
370   }\r
371 \r
372   //\r
373   // Enumerate all data and erasing the target item.\r
374   //\r
375   IsItemFound = FALSE;\r
376   ItemDataSize = (UINT32) DataSize;\r
377   CertList = (EFI_SIGNATURE_LIST *) OldData;\r
378   Offset = 0;\r
379   GuidIndex = 0;\r
380   while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
381     if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
382       //\r
383       // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.\r
384       //\r
385       CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
386       NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);\r
387       Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
388       Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
389       CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
390       for (Index = 0; Index < CertCount; Index++) {\r
391         if (GuidIndex == DeleteIndex) {\r
392           //\r
393           // Find it! Skip it!\r
394           //\r
395           NewCertList->SignatureListSize -= CertList->SignatureSize;\r
396           IsItemFound = TRUE;\r
397         } else {\r
398           //\r
399           // This item doesn't match. Copy it to the Data buffer.\r
400           //\r
401           CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);\r
402           Offset += CertList->SignatureSize;\r
403         }\r
404         GuidIndex++;\r
405         Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
406       }\r
407     } else {\r
408       //\r
409       // This List doesn't match. Just copy it to the Data buffer.\r
410       //\r
411       CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
412       Offset += CertList->SignatureListSize;\r
413     }\r
414 \r
415     ItemDataSize -= CertList->SignatureListSize;\r
416     CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
417   }\r
418 \r
419   if (!IsItemFound) {\r
420     //\r
421     // Doesn't find the signature Item!\r
422     //\r
423     Status = EFI_NOT_FOUND;\r
424     goto ON_EXIT;\r
425   }\r
426 \r
427   //\r
428   // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.\r
429   //\r
430   ItemDataSize = Offset;\r
431   CertList = (EFI_SIGNATURE_LIST *) Data;\r
432   Offset = 0;\r
433   ZeroMem (OldData, ItemDataSize);\r
434   while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
435     CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
436     DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));\r
437     if (CertCount != 0) {\r
438       CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
439       Offset += CertList->SignatureListSize;\r
440     }\r
441     ItemDataSize -= CertList->SignatureListSize;\r
442     CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
443   }\r
444 \r
445   DataSize = Offset;\r
446 \r
447   Status = gRT->SetVariable(\r
448                   VariableName,\r
449                   VendorGuid,\r
450                   Attr,\r
451                   DataSize,\r
452                   OldData\r
453                   );\r
454   if (EFI_ERROR (Status)) {\r
455     DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
456     goto ON_EXIT;\r
457   }\r
458 \r
459 ON_EXIT:\r
460   if (Data != NULL) {\r
461     FreePool(Data);\r
462   }\r
463 \r
464   if (OldData != NULL) {\r
465     FreePool(OldData);\r
466   }\r
467 \r
468   return UpdateDeletePage (\r
469            Private,\r
470            VariableName,\r
471            VendorGuid,\r
472            LabelNumber,\r
473            FormId,\r
474            QuestionIdBase\r
475            );\r
476 }\r
477 \r
478 \r
479 /**\r
480   Close an open file handle.\r
481 \r
482   @param[in] FileHandle           The file handle to close.\r
483 \r
484 **/\r
485 VOID\r
486 CloseFile (\r
487   IN EFI_FILE_HANDLE   FileHandle\r
488   )\r
489 {\r
490   if (FileHandle != NULL) {\r
491     FileHandle->Close (FileHandle);\r
492   }\r
493 }\r
494 \r
495 /**\r
496   Read file content into BufferPtr, the size of the allocate buffer\r
497   is *FileSize plus AddtionAllocateSize.\r
498 \r
499   @param[in]       FileHandle            The file to be read.\r
500   @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.\r
501   @param[out]      FileSize              Size of input file\r
502   @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated.\r
503                                          In case the buffer need to contain others besides the file content.\r
504 \r
505   @retval   EFI_SUCCESS                  The file was read into the buffer.\r
506   @retval   EFI_INVALID_PARAMETER        A parameter was invalid.\r
507   @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.\r
508   @retval   others                       Unexpected error.\r
509 \r
510 **/\r
511 EFI_STATUS\r
512 ReadFileContent (\r
513   IN      EFI_FILE_HANDLE           FileHandle,\r
514   IN OUT  VOID                      **BufferPtr,\r
515      OUT  UINTN                     *FileSize,\r
516   IN      UINTN                     AddtionAllocateSize\r
517   )\r
518 \r
519 {\r
520   UINTN      BufferSize;\r
521   UINT64     SourceFileSize;\r
522   VOID       *Buffer;\r
523   EFI_STATUS Status;\r
524 \r
525   if ((FileHandle == NULL) || (FileSize == NULL)) {\r
526     return EFI_INVALID_PARAMETER;\r
527   }\r
528 \r
529   Buffer = NULL;\r
530 \r
531   //\r
532   // Get the file size\r
533   //\r
534   Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);\r
535   if (EFI_ERROR (Status)) {\r
536     goto ON_EXIT;\r
537   }\r
538 \r
539   Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);\r
540   if (EFI_ERROR (Status)) {\r
541     goto ON_EXIT;\r
542   }\r
543 \r
544   Status = FileHandle->SetPosition (FileHandle, 0);\r
545   if (EFI_ERROR (Status)) {\r
546     goto ON_EXIT;\r
547   }\r
548 \r
549   BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;\r
550   Buffer =  AllocateZeroPool(BufferSize);\r
551   if (Buffer == NULL) {\r
552     return EFI_OUT_OF_RESOURCES;\r
553   }\r
554 \r
555   BufferSize = (UINTN) SourceFileSize;\r
556   *FileSize  = BufferSize;\r
557 \r
558   Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);\r
559   if (EFI_ERROR (Status) || BufferSize != *FileSize) {\r
560     FreePool (Buffer);\r
561     Buffer = NULL;\r
562     Status  = EFI_BAD_BUFFER_SIZE;\r
563     goto ON_EXIT;\r
564   }\r
565 \r
566 ON_EXIT:\r
567 \r
568   *BufferPtr = Buffer;\r
569   return Status;\r
570 }\r
571 \r
572 /**\r
573   This function will open a file or directory referenced by DevicePath.\r
574 \r
575   This function opens a file with the open mode according to the file path. The\r
576   Attributes is valid only for EFI_FILE_MODE_CREATE.\r
577 \r
578   @param[in, out]  FilePath        On input, the device path to the file.\r
579                                    On output, the remaining device path.\r
580   @param[out]      FileHandle      Pointer to the file handle.\r
581   @param[in]       OpenMode        The mode to open the file with.\r
582   @param[in]       Attributes      The file's file attributes.\r
583 \r
584   @retval EFI_SUCCESS              The information was set.\r
585   @retval EFI_INVALID_PARAMETER    One of the parameters has an invalid value.\r
586   @retval EFI_UNSUPPORTED          Could not open the file path.\r
587   @retval EFI_NOT_FOUND            The specified file could not be found on the\r
588                                    device or the file system could not be found on\r
589                                    the device.\r
590   @retval EFI_NO_MEDIA             The device has no medium.\r
591   @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the\r
592                                    medium is no longer supported.\r
593   @retval EFI_DEVICE_ERROR         The device reported an error.\r
594   @retval EFI_VOLUME_CORRUPTED     The file system structures are corrupted.\r
595   @retval EFI_WRITE_PROTECTED      The file or medium is write protected.\r
596   @retval EFI_ACCESS_DENIED        The file was opened read only.\r
597   @retval EFI_OUT_OF_RESOURCES     Not enough resources were available to open the\r
598                                    file.\r
599   @retval EFI_VOLUME_FULL          The volume is full.\r
600 **/\r
601 EFI_STATUS\r
602 EFIAPI\r
603 OpenFileByDevicePath (\r
604   IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,\r
605   OUT EFI_FILE_HANDLE                 *FileHandle,\r
606   IN UINT64                           OpenMode,\r
607   IN UINT64                           Attributes\r
608   )\r
609 {\r
610   EFI_STATUS                      Status;\r
611   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
612   EFI_FILE_PROTOCOL               *Handle1;\r
613   EFI_FILE_PROTOCOL               *Handle2;\r
614   EFI_HANDLE                      DeviceHandle;\r
615 \r
616   if ((FilePath == NULL || FileHandle == NULL)) {\r
617     return EFI_INVALID_PARAMETER;\r
618   }\r
619 \r
620   Status = gBS->LocateDevicePath (\r
621                   &gEfiSimpleFileSystemProtocolGuid,\r
622                   FilePath,\r
623                   &DeviceHandle\r
624                   );\r
625   if (EFI_ERROR (Status)) {\r
626     return Status;\r
627   }\r
628 \r
629   Status = gBS->OpenProtocol(\r
630                   DeviceHandle,\r
631                   &gEfiSimpleFileSystemProtocolGuid,\r
632                   (VOID**)&EfiSimpleFileSystemProtocol,\r
633                   gImageHandle,\r
634                   NULL,\r
635                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
636                   );\r
637   if (EFI_ERROR (Status)) {\r
638     return Status;\r
639   }\r
640 \r
641   Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);\r
642   if (EFI_ERROR (Status)) {\r
643     FileHandle = NULL;\r
644     return Status;\r
645   }\r
646 \r
647   //\r
648   // go down directories one node at a time.\r
649   //\r
650   while (!IsDevicePathEnd (*FilePath)) {\r
651     //\r
652     // For file system access each node should be a file path component\r
653     //\r
654     if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||\r
655         DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
656        ) {\r
657       FileHandle = NULL;\r
658       return (EFI_INVALID_PARAMETER);\r
659     }\r
660     //\r
661     // Open this file path node\r
662     //\r
663     Handle2  = Handle1;\r
664     Handle1 = NULL;\r
665 \r
666     //\r
667     // Try to test opening an existing file\r
668     //\r
669     Status = Handle2->Open (\r
670                         Handle2,\r
671                         &Handle1,\r
672                         ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
673                         OpenMode &~EFI_FILE_MODE_CREATE,\r
674                         0\r
675                         );\r
676 \r
677     //\r
678     // see if the error was that it needs to be created\r
679     //\r
680     if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
681       Status = Handle2->Open (\r
682                           Handle2,\r
683                           &Handle1,\r
684                           ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
685                           OpenMode,\r
686                           Attributes\r
687                           );\r
688     }\r
689     //\r
690     // Close the last node\r
691     //\r
692     Handle2->Close (Handle2);\r
693 \r
694     if (EFI_ERROR(Status)) {\r
695       return (Status);\r
696     }\r
697 \r
698     //\r
699     // Get the next node\r
700     //\r
701     *FilePath = NextDevicePathNode (*FilePath);\r
702   }\r
703 \r
704   //\r
705   // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!\r
706   //\r
707   *FileHandle = (VOID*)Handle1;\r
708   return EFI_SUCCESS;\r
709 }\r
710 \r
711 /**\r
712   This function converts an input device structure to a Unicode string.\r
713 \r
714   @param[in] DevPath                  A pointer to the device path structure.\r
715 \r
716   @return A new allocated Unicode string that represents the device path.\r
717 \r
718 **/\r
719 CHAR16 *\r
720 EFIAPI\r
721 DevicePathToStr (\r
722   IN EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
723   )\r
724 {\r
725   return ConvertDevicePathToText (\r
726            DevPath,\r
727            FALSE,\r
728            TRUE\r
729            );\r
730 }\r
731 \r
732 \r
733 /**\r
734   Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.\r
735   The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL\r
736   means not enough memory resource.\r
737 \r
738   @param DevicePath       Device path.\r
739 \r
740   @retval NULL            Not enough memory resourece for AllocateCopyPool.\r
741   @retval Other           A new allocated string that represents the file name.\r
742 \r
743 **/\r
744 CHAR16 *\r
745 ExtractFileNameFromDevicePath (\r
746   IN   EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
747   )\r
748 {\r
749   CHAR16          *String;\r
750   CHAR16          *MatchString;\r
751   CHAR16          *LastMatch;\r
752   CHAR16          *FileName;\r
753   UINTN           Length;\r
754 \r
755   ASSERT(DevicePath != NULL);\r
756 \r
757   String = DevicePathToStr(DevicePath);\r
758   MatchString = String;\r
759   LastMatch   = String;\r
760   FileName    = NULL;\r
761 \r
762   while(MatchString != NULL){\r
763     LastMatch   = MatchString + 1;\r
764     MatchString = StrStr(LastMatch,L"\\");\r
765   }\r
766 \r
767   Length = StrLen(LastMatch);\r
768   FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);\r
769   if (FileName != NULL) {\r
770     *(FileName + Length) = 0;\r
771   }\r
772 \r
773   FreePool(String);\r
774 \r
775   return FileName;\r
776 }\r
777 \r
778 /**\r
779   Enroll a new X509 certificate into Variable.\r
780 \r
781   @param[in] PrivateData     The module's private data.\r
782   @param[in] VariableName    Variable name of CA database.\r
783 \r
784   @retval   EFI_SUCCESS            New X509 is enrolled successfully.\r
785   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.\r
786 \r
787 **/\r
788 EFI_STATUS\r
789 EnrollX509toVariable (\r
790   IN TLS_AUTH_CONFIG_PRIVATE_DATA   *Private,\r
791   IN CHAR16                         *VariableName\r
792   )\r
793 {\r
794   EFI_STATUS                        Status;\r
795   UINTN                             X509DataSize;\r
796   VOID                              *X509Data;\r
797   EFI_SIGNATURE_LIST                *CACert;\r
798   EFI_SIGNATURE_DATA                *CACertData;\r
799   VOID                              *Data;\r
800   UINTN                             DataSize;\r
801   UINTN                             SigDataSize;\r
802   UINT32                            Attr;\r
803 \r
804   X509DataSize  = 0;\r
805   SigDataSize   = 0;\r
806   DataSize      = 0;\r
807   X509Data      = NULL;\r
808   CACert        = NULL;\r
809   CACertData    = NULL;\r
810   Data          = NULL;\r
811 \r
812   Status = ReadFileContent (\r
813              Private->FileContext->FHandle,\r
814              &X509Data,\r
815              &X509DataSize,\r
816              0\r
817              );\r
818   if (EFI_ERROR (Status)) {\r
819     goto ON_EXIT;\r
820   }\r
821   ASSERT (X509Data != NULL);\r
822 \r
823   SigDataSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;\r
824 \r
825   Data = AllocateZeroPool (SigDataSize);\r
826   if (Data == NULL) {\r
827     Status = EFI_OUT_OF_RESOURCES;\r
828     goto ON_EXIT;\r
829   }\r
830 \r
831   //\r
832   // Fill Certificate Database parameters.\r
833   //\r
834   CACert = (EFI_SIGNATURE_LIST*) Data;\r
835   CACert->SignatureListSize   = (UINT32) SigDataSize;\r
836   CACert->SignatureHeaderSize = 0;\r
837   CACert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
838   CopyGuid (&CACert->SignatureType, &gEfiCertX509Guid);\r
839 \r
840   CACertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) CACert + sizeof (EFI_SIGNATURE_LIST));\r
841   CopyGuid (&CACertData->SignatureOwner, Private->CertGuid);\r
842   CopyMem ((UINT8* ) (CACertData->SignatureData), X509Data, X509DataSize);\r
843 \r
844   //\r
845   // Check if signature database entry has been already existed.\r
846   // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
847   // new signature data to original variable\r
848   //\r
849   Attr = TLS_AUTH_CONFIG_VAR_BASE_ATTR;\r
850 \r
851   Status = gRT->GetVariable(\r
852                   VariableName,\r
853                   &gEfiTlsCaCertificateGuid,\r
854                   NULL,\r
855                   &DataSize,\r
856                   NULL\r
857                   );\r
858   if (Status == EFI_BUFFER_TOO_SMALL) {\r
859     Attr |= EFI_VARIABLE_APPEND_WRITE;\r
860   } else if (Status != EFI_NOT_FOUND) {\r
861     goto ON_EXIT;\r
862   }\r
863 \r
864   Status = gRT->SetVariable(\r
865                   VariableName,\r
866                   &gEfiTlsCaCertificateGuid,\r
867                   Attr,\r
868                   SigDataSize,\r
869                   Data\r
870                   );\r
871   if (EFI_ERROR (Status)) {\r
872     goto ON_EXIT;\r
873   }\r
874 \r
875 ON_EXIT:\r
876 \r
877   CloseFile (Private->FileContext->FHandle);\r
878   if (Private->FileContext->FileName != NULL) {\r
879     FreePool(Private->FileContext->FileName);\r
880     Private->FileContext->FileName = NULL;\r
881   }\r
882 \r
883   Private->FileContext->FHandle = NULL;\r
884 \r
885   if (Private->CertGuid != NULL) {\r
886     FreePool (Private->CertGuid);\r
887     Private->CertGuid = NULL;\r
888   }\r
889 \r
890   if (Data != NULL) {\r
891     FreePool (Data);\r
892   }\r
893 \r
894   if (X509Data != NULL) {\r
895     FreePool (X509Data);\r
896   }\r
897 \r
898   return Status;\r
899 }\r
900 \r
901 /**\r
902   Enroll Cert into TlsCaCertificate. The GUID will be Private->CertGuid.\r
903 \r
904   @param[in] PrivateData     The module's private data.\r
905   @param[in] VariableName    Variable name of signature database.\r
906 \r
907   @retval   EFI_SUCCESS            New Cert enrolled successfully.\r
908   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.\r
909   @retval   EFI_UNSUPPORTED        The Cert file is unsupported type.\r
910   @retval   others                 Fail to enroll Cert data.\r
911 \r
912 **/\r
913 EFI_STATUS\r
914 EnrollCertDatabase (\r
915   IN TLS_AUTH_CONFIG_PRIVATE_DATA  *Private,\r
916   IN CHAR16                        *VariableName\r
917   )\r
918 {\r
919   UINT16*      FilePostFix;\r
920   UINTN        NameLength;\r
921 \r
922   if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->CertGuid == NULL)) {\r
923     return EFI_INVALID_PARAMETER;\r
924   }\r
925 \r
926   //\r
927   // Parse the file's postfix.\r
928   //\r
929   NameLength = StrLen (Private->FileContext->FileName);\r
930   if (NameLength <= 4) {\r
931     return EFI_INVALID_PARAMETER;\r
932   }\r
933   FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
934 \r
935   if (IsDerPemEncodeCertificate (FilePostFix)) {\r
936     //\r
937     // Supports DER-encoded X509 certificate.\r
938     //\r
939     return EnrollX509toVariable (Private, VariableName);\r
940   }\r
941 \r
942   return EFI_UNSUPPORTED;\r
943 }\r
944 \r
945 /**\r
946   Refresh the global UpdateData structure.\r
947 \r
948 **/\r
949 VOID\r
950 RefreshUpdateData (\r
951   VOID\r
952   )\r
953 {\r
954   //\r
955   // Free current updated date\r
956   //\r
957   if (mStartOpCodeHandle != NULL) {\r
958     HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
959   }\r
960 \r
961   //\r
962   // Create new OpCode Handle\r
963   //\r
964   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
965 \r
966   //\r
967   // Create Hii Extend Label OpCode as the start opcode\r
968   //\r
969   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
970                                          mStartOpCodeHandle,\r
971                                          &gEfiIfrTianoGuid,\r
972                                          NULL,\r
973                                          sizeof (EFI_IFR_GUID_LABEL)\r
974                                          );\r
975   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
976 }\r
977 \r
978 /**\r
979   Clean up the dynamic opcode at label and form specified by both LabelId.\r
980 \r
981   @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.\r
982   @param[in] PrivateData     Module private data.\r
983 \r
984 **/\r
985 VOID\r
986 CleanUpPage (\r
987   IN UINT16                           LabelId,\r
988   IN TLS_AUTH_CONFIG_PRIVATE_DATA     *PrivateData\r
989   )\r
990 {\r
991   RefreshUpdateData ();\r
992 \r
993   //\r
994   // Remove all op-codes from dynamic page\r
995   //\r
996   mStartLabel->Number = LabelId;\r
997   HiiUpdateForm (\r
998     PrivateData->RegisteredHandle,\r
999     &gTlsAuthConfigGuid,\r
1000     LabelId,\r
1001     mStartOpCodeHandle, // Label LabelId\r
1002     mEndOpCodeHandle    // LABEL_END\r
1003     );\r
1004 }\r
1005 \r
1006 /**\r
1007   Update the form base on the selected file.\r
1008 \r
1009   @param FilePath   Point to the file path.\r
1010   @param FormId     The form need to display.\r
1011 \r
1012   @retval TRUE   Exit caller function.\r
1013   @retval FALSE  Not exit caller function.\r
1014 \r
1015 **/\r
1016 BOOLEAN\r
1017 UpdatePage(\r
1018   IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,\r
1019   IN  EFI_FORM_ID               FormId\r
1020   )\r
1021 {\r
1022   CHAR16                *FileName;\r
1023   EFI_STRING_ID         StringToken;\r
1024 \r
1025   FileName = NULL;\r
1026 \r
1027   if (FilePath != NULL) {\r
1028     FileName = ExtractFileNameFromDevicePath(FilePath);\r
1029   }\r
1030   if (FileName == NULL) {\r
1031     //\r
1032     // FileName = NULL has two case:\r
1033     // 1. FilePath == NULL, not select file.\r
1034     // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.\r
1035     // In these two case, no need to update the form, and exit the caller function.\r
1036     //\r
1037     return TRUE;\r
1038   }\r
1039   StringToken =  HiiSetString (mTlsAuthPrivateData->RegisteredHandle, 0, FileName, NULL);\r
1040 \r
1041   mTlsAuthPrivateData->FileContext->FileName = FileName;\r
1042 \r
1043   OpenFileByDevicePath (\r
1044     &FilePath,\r
1045     &mTlsAuthPrivateData->FileContext->FHandle,\r
1046     EFI_FILE_MODE_READ,\r
1047     0\r
1048     );\r
1049   //\r
1050   // Create Subtitle op-code for the display string of the option.\r
1051   //\r
1052   RefreshUpdateData ();\r
1053   mStartLabel->Number = FormId;\r
1054 \r
1055   HiiCreateSubTitleOpCode (\r
1056     mStartOpCodeHandle,\r
1057     StringToken,\r
1058     0,\r
1059     0,\r
1060     0\r
1061    );\r
1062 \r
1063   HiiUpdateForm (\r
1064     mTlsAuthPrivateData->RegisteredHandle,\r
1065     &gTlsAuthConfigGuid,\r
1066     FormId,\r
1067     mStartOpCodeHandle, /// Label FormId\r
1068     mEndOpCodeHandle    /// LABEL_END\r
1069     );\r
1070 \r
1071   return TRUE;\r
1072 }\r
1073 \r
1074 /**\r
1075   Update the form base on the input file path info.\r
1076 \r
1077   @param FilePath    Point to the file path.\r
1078 \r
1079   @retval TRUE   Exit caller function.\r
1080   @retval FALSE  Not exit caller function.\r
1081 **/\r
1082 BOOLEAN\r
1083 EFIAPI\r
1084 UpdateCAFromFile (\r
1085   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath\r
1086   )\r
1087 {\r
1088   return UpdatePage(FilePath, TLS_AUTH_CONFIG_FORMID4_FORM);\r
1089 }\r
1090 \r
1091 /**\r
1092   Unload the configuration form, this includes: delete all the configuration\r
1093   entries, uninstall the form callback protocol, and free the resources used.\r
1094 \r
1095   @param[in]  Private             Pointer to the driver private data.\r
1096 \r
1097   @retval EFI_SUCCESS             The configuration form is unloaded.\r
1098   @retval Others                  Failed to unload the form.\r
1099 \r
1100 **/\r
1101 EFI_STATUS\r
1102 TlsAuthConfigFormUnload (\r
1103   IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private\r
1104   )\r
1105 {\r
1106   if (Private->DriverHandle != NULL) {\r
1107     //\r
1108     // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
1109     //\r
1110     gBS->UninstallMultipleProtocolInterfaces (\r
1111            Private->DriverHandle,\r
1112            &gEfiDevicePathProtocolGuid,\r
1113            &mTlsAuthConfigHiiVendorDevicePath,\r
1114            &gEfiHiiConfigAccessProtocolGuid,\r
1115            &Private->ConfigAccess,\r
1116            NULL\r
1117            );\r
1118     Private->DriverHandle = NULL;\r
1119   }\r
1120 \r
1121   if (Private->RegisteredHandle != NULL) {\r
1122     //\r
1123     // Remove HII package list\r
1124     //\r
1125     HiiRemovePackages (Private->RegisteredHandle);\r
1126     Private->RegisteredHandle = NULL;\r
1127   }\r
1128 \r
1129   if (Private->CertGuid != NULL) {\r
1130     FreePool (Private->CertGuid);\r
1131   }\r
1132 \r
1133   if (Private->FileContext != NULL) {\r
1134     FreePool (Private->FileContext);\r
1135   }\r
1136 \r
1137   FreePool (Private);\r
1138 \r
1139   if (mStartOpCodeHandle != NULL) {\r
1140     HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
1141   }\r
1142 \r
1143   if (mEndOpCodeHandle != NULL) {\r
1144     HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
1145   }\r
1146 \r
1147   return EFI_SUCCESS;\r
1148 }\r
1149 \r
1150 \r
1151 /**\r
1152   Initialize the configuration form.\r
1153 \r
1154   @param[in]  Private             Pointer to the driver private data.\r
1155 \r
1156   @retval EFI_SUCCESS             The configuration form is initialized.\r
1157   @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.\r
1158 \r
1159 **/\r
1160 EFI_STATUS\r
1161 TlsAuthConfigFormInit (\r
1162   IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private\r
1163   )\r
1164 {\r
1165   EFI_STATUS                        Status;\r
1166 \r
1167   Private->Signature = TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE;\r
1168 \r
1169   Private->ConfigAccess.ExtractConfig = TlsAuthConfigAccessExtractConfig;\r
1170   Private->ConfigAccess.RouteConfig   = TlsAuthConfigAccessRouteConfig;\r
1171   Private->ConfigAccess.Callback      = TlsAuthConfigAccessCallback;\r
1172 \r
1173   //\r
1174   // Install Device Path Protocol and Config Access protocol to driver handle.\r
1175   //\r
1176   Status = gBS->InstallMultipleProtocolInterfaces (\r
1177                   &Private->DriverHandle,\r
1178                   &gEfiDevicePathProtocolGuid,\r
1179                   &mTlsAuthConfigHiiVendorDevicePath,\r
1180                   &gEfiHiiConfigAccessProtocolGuid,\r
1181                   &Private->ConfigAccess,\r
1182                   NULL\r
1183                   );\r
1184   if (EFI_ERROR (Status)) {\r
1185     return Status;\r
1186   }\r
1187 \r
1188   //\r
1189   // Publish our HII data.\r
1190   //\r
1191   Private->RegisteredHandle = HiiAddPackages (\r
1192                                 &gTlsAuthConfigGuid,\r
1193                                 Private->DriverHandle,\r
1194                                 TlsAuthConfigDxeStrings,\r
1195                                 TlsAuthConfigVfrBin,\r
1196                                 NULL\r
1197                                 );\r
1198   if (Private->RegisteredHandle == NULL) {\r
1199     Status = EFI_OUT_OF_RESOURCES;\r
1200     goto Error;\r
1201   }\r
1202 \r
1203   Private->FileContext = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_FILE_CONTEXT));\r
1204   if (Private->FileContext == NULL) {\r
1205     Status = EFI_OUT_OF_RESOURCES;\r
1206     goto Error;\r
1207   }\r
1208 \r
1209   //\r
1210   // Init OpCode Handle and Allocate space for creation of Buffer\r
1211   //\r
1212   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1213   if (mStartOpCodeHandle == NULL) {\r
1214     Status = EFI_OUT_OF_RESOURCES;\r
1215     goto Error;\r
1216   }\r
1217 \r
1218   mEndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1219   if (mEndOpCodeHandle == NULL) {\r
1220     Status = EFI_OUT_OF_RESOURCES;\r
1221     goto Error;\r
1222   }\r
1223 \r
1224   //\r
1225   // Create Hii Extend Label OpCode as the start opcode\r
1226   //\r
1227   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
1228                                          mStartOpCodeHandle,\r
1229                                          &gEfiIfrTianoGuid,\r
1230                                          NULL,\r
1231                                          sizeof (EFI_IFR_GUID_LABEL)\r
1232                                          );\r
1233   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1234 \r
1235   //\r
1236   // Create Hii Extend Label OpCode as the end opcode\r
1237   //\r
1238   mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
1239                                        mEndOpCodeHandle,\r
1240                                        &gEfiIfrTianoGuid,\r
1241                                        NULL,\r
1242                                        sizeof (EFI_IFR_GUID_LABEL)\r
1243                                        );\r
1244   mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1245   mEndLabel->Number       = LABEL_END;\r
1246 \r
1247   return EFI_SUCCESS;\r
1248 \r
1249 Error:\r
1250   TlsAuthConfigFormUnload (Private);\r
1251   return Status;\r
1252 }\r
1253 \r
1254 /**\r
1255 \r
1256   This function allows the caller to request the current\r
1257   configuration for one or more named elements. The resulting\r
1258   string is in <ConfigAltResp> format. Any and all alternative\r
1259   configuration strings shall also be appended to the end of the\r
1260   current configuration string. If they are, they must appear\r
1261   after the current configuration. They must contain the same\r
1262   routing (GUID, NAME, PATH) as the current configuration string.\r
1263   They must have an additional description indicating the type of\r
1264   alternative configuration the string represents,\r
1265   "ALTCFG=<StringToken>". That <StringToken> (when\r
1266   converted from Hex UNICODE to binary) is a reference to a\r
1267   string in the associated string pack.\r
1268 \r
1269   @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1270 \r
1271   @param Request    A null-terminated Unicode string in\r
1272                     <ConfigRequest> format. Note that this\r
1273                     includes the routing information as well as\r
1274                     the configurable name / value pairs. It is\r
1275                     invalid for this string to be in\r
1276                     <MultiConfigRequest> format.\r
1277                     If a NULL is passed in for the Request field,\r
1278                     all of the settings being abstracted by this function\r
1279                     will be returned in the Results field.  In addition,\r
1280                     if a ConfigHdr is passed in with no request elements,\r
1281                     all of the settings being abstracted for that particular\r
1282                     ConfigHdr reference will be returned in the Results Field.\r
1283 \r
1284   @param Progress   On return, points to a character in the\r
1285                     Request string. Points to the string's null\r
1286                     terminator if request was successful. Points\r
1287                     to the most recent "&" before the first\r
1288                     failing name / value pair (or the beginning\r
1289                     of the string if the failure is in the first\r
1290                     name / value pair) if the request was not\r
1291                     successful.\r
1292 \r
1293   @param Results    A null-terminated Unicode string in\r
1294                     <MultiConfigAltResp> format which has all values\r
1295                     filled in for the names in the Request string.\r
1296                     String to be allocated by the called function.\r
1297 \r
1298   @retval EFI_SUCCESS             The Results string is filled with the\r
1299                                   values corresponding to all requested\r
1300                                   names.\r
1301 \r
1302   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the\r
1303                                   parts of the results that must be\r
1304                                   stored awaiting possible future\r
1305                                   protocols.\r
1306 \r
1307   @retval EFI_NOT_FOUND           Routing data doesn't match any\r
1308                                   known driver. Progress set to the\r
1309                                   first character in the routing header.\r
1310                                   Note: There is no requirement that the\r
1311                                   driver validate the routing data. It\r
1312                                   must skip the <ConfigHdr> in order to\r
1313                                   process the names.\r
1314 \r
1315   @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set\r
1316                                   to most recent "&" before the\r
1317                                   error or the beginning of the\r
1318                                   string.\r
1319 \r
1320   @retval EFI_INVALID_PARAMETER   Unknown name. Progress points\r
1321                                   to the & before the name in\r
1322                                   question.\r
1323 \r
1324 **/\r
1325 EFI_STATUS\r
1326 EFIAPI\r
1327 TlsAuthConfigAccessExtractConfig (\r
1328   IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,\r
1329   IN CONST  EFI_STRING                      Request,\r
1330   OUT       EFI_STRING                      *Progress,\r
1331   OUT       EFI_STRING                      *Results\r
1332   )\r
1333 {\r
1334   EFI_STATUS                        Status;\r
1335   UINTN                             BufferSize;\r
1336   UINTN                             Size;\r
1337   EFI_STRING                        ConfigRequest;\r
1338   EFI_STRING                        ConfigRequestHdr;\r
1339   TLS_AUTH_CONFIG_PRIVATE_DATA      *Private;\r
1340   BOOLEAN                           AllocatedRequest;\r
1341 \r
1342   if (Progress == NULL || Results == NULL) {\r
1343     return EFI_INVALID_PARAMETER;\r
1344   }\r
1345 \r
1346   AllocatedRequest = FALSE;\r
1347   ConfigRequestHdr = NULL;\r
1348   ConfigRequest    = NULL;\r
1349   Size             = 0;\r
1350 \r
1351   Private          = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);\r
1352 \r
1353   BufferSize       = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);\r
1354   ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);\r
1355 \r
1356   *Progress        = Request;\r
1357 \r
1358   if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {\r
1359     return EFI_NOT_FOUND;\r
1360   }\r
1361 \r
1362   ConfigRequest = Request;\r
1363   if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
1364     //\r
1365     // Request is set to NULL or OFFSET is NULL, construct full request string.\r
1366     //\r
1367     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
1368     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
1369     //\r
1370     ConfigRequestHdr = HiiConstructConfigHdr (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, Private->DriverHandle);\r
1371     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
1372     ConfigRequest = AllocateZeroPool (Size);\r
1373     ASSERT (ConfigRequest != NULL);\r
1374     AllocatedRequest = TRUE;\r
1375     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
1376     FreePool (ConfigRequestHdr);\r
1377     ConfigRequestHdr = NULL;\r
1378   }\r
1379 \r
1380   Status = gHiiConfigRouting->BlockToConfig (\r
1381                                 gHiiConfigRouting,\r
1382                                 ConfigRequest,\r
1383                                 (UINT8 *) &Private->TlsAuthConfigNvData,\r
1384                                 BufferSize,\r
1385                                 Results,\r
1386                                 Progress\r
1387                                 );\r
1388 \r
1389   //\r
1390   // Free the allocated config request string.\r
1391   //\r
1392   if (AllocatedRequest) {\r
1393     FreePool (ConfigRequest);\r
1394   }\r
1395 \r
1396   //\r
1397   // Set Progress string to the original request string.\r
1398   //\r
1399   if (Request == NULL) {\r
1400     *Progress = NULL;\r
1401   } else if (StrStr (Request, L"OFFSET") == NULL) {\r
1402     *Progress = Request + StrLen (Request);\r
1403   }\r
1404 \r
1405   return Status;\r
1406 }\r
1407 \r
1408 /**\r
1409 \r
1410   This function applies changes in a driver's configuration.\r
1411   Input is a Configuration, which has the routing data for this\r
1412   driver followed by name / value configuration pairs. The driver\r
1413   must apply those pairs to its configurable storage. If the\r
1414   driver's configuration is stored in a linear block of data\r
1415   and the driver's name / value pairs are in <BlockConfig>\r
1416   format, it may use the ConfigToBlock helper function (above) to\r
1417   simplify the job.\r
1418 \r
1419   @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1420 \r
1421   @param Configuration  A null-terminated Unicode string in\r
1422                         <ConfigString> format.\r
1423 \r
1424   @param Progress       A pointer to a string filled in with the\r
1425                         offset of the most recent '&' before the\r
1426                         first failing name / value pair (or the\r
1427                         beginn ing of the string if the failure\r
1428                         is in the first name / value pair) or\r
1429                         the terminating NULL if all was\r
1430                         successful.\r
1431 \r
1432   @retval EFI_SUCCESS             The results have been distributed or are\r
1433                                   awaiting distribution.\r
1434 \r
1435   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the\r
1436                                   parts of the results that must be\r
1437                                   stored awaiting possible future\r
1438                                   protocols.\r
1439 \r
1440   @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the\r
1441                                   Results parameter would result\r
1442                                   in this type of error.\r
1443 \r
1444   @retval EFI_NOT_FOUND           Target for the specified routing data\r
1445                                   was not found\r
1446 \r
1447 **/\r
1448 EFI_STATUS\r
1449 EFIAPI\r
1450 TlsAuthConfigAccessRouteConfig (\r
1451   IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,\r
1452   IN CONST  EFI_STRING                      Configuration,\r
1453   OUT       EFI_STRING                      *Progress\r
1454   )\r
1455 {\r
1456   EFI_STATUS                       Status;\r
1457   UINTN                            BufferSize;\r
1458   TLS_AUTH_CONFIG_PRIVATE_DATA     *Private;\r
1459 \r
1460   if (Progress == NULL) {\r
1461     return EFI_INVALID_PARAMETER;\r
1462   }\r
1463   *Progress = Configuration;\r
1464 \r
1465   if (Configuration == NULL) {\r
1466     return EFI_INVALID_PARAMETER;\r
1467   }\r
1468 \r
1469   //\r
1470   // Check routing data in <ConfigHdr>.\r
1471   // Note: there is no name for Name/Value storage, only GUID will be checked\r
1472   //\r
1473   if (!HiiIsConfigHdrMatch (Configuration, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {\r
1474     return EFI_NOT_FOUND;\r
1475   }\r
1476 \r
1477   Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);\r
1478 \r
1479   BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);\r
1480   ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);\r
1481 \r
1482   Status = gHiiConfigRouting->ConfigToBlock (\r
1483                                 gHiiConfigRouting,\r
1484                                 Configuration,\r
1485                                 (UINT8 *) &Private->TlsAuthConfigNvData,\r
1486                                 &BufferSize,\r
1487                                 Progress\r
1488                                 );\r
1489   if (EFI_ERROR (Status)) {\r
1490     return Status;\r
1491   }\r
1492 \r
1493   return Status;\r
1494 }\r
1495 \r
1496 /**\r
1497 \r
1498   This function is called to provide results data to the driver.\r
1499   This data consists of a unique key that is used to identify\r
1500   which data is either being passed back or being asked for.\r
1501 \r
1502   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1503   @param  Action                 Specifies the type of action taken by the browser.\r
1504   @param  QuestionId             A unique value which is sent to the original\r
1505                                  exporting driver so that it can identify the type\r
1506                                  of data to expect. The format of the data tends to\r
1507                                  vary based on the opcode that generated the callback.\r
1508   @param  Type                   The type of value for the question.\r
1509   @param  Value                  A pointer to the data being sent to the original\r
1510                                  exporting driver.\r
1511   @param  ActionRequest          On return, points to the action requested by the\r
1512                                  callback function.\r
1513 \r
1514   @retval EFI_SUCCESS            The callback successfully handled the action.\r
1515   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the\r
1516                                  variable and its data.\r
1517   @retval EFI_DEVICE_ERROR       The variable could not be saved.\r
1518   @retval EFI_UNSUPPORTED        The specified Action is not supported by the\r
1519                                  callback.\r
1520 **/\r
1521 EFI_STATUS\r
1522 EFIAPI\r
1523 TlsAuthConfigAccessCallback (\r
1524   IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
1525   IN     EFI_BROWSER_ACTION                     Action,\r
1526   IN     EFI_QUESTION_ID                        QuestionId,\r
1527   IN     UINT8                                  Type,\r
1528   IN OUT EFI_IFR_TYPE_VALUE                     *Value,\r
1529   OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
1530   )\r
1531 {\r
1532   EFI_INPUT_KEY                   Key;\r
1533   EFI_STATUS                      Status;\r
1534   RETURN_STATUS                   RStatus;\r
1535   TLS_AUTH_CONFIG_PRIVATE_DATA    *Private;\r
1536   UINTN                           BufferSize;\r
1537   TLS_AUTH_CONFIG_IFR_NVDATA      *IfrNvData;\r
1538   UINT16                          LabelId;\r
1539   EFI_DEVICE_PATH_PROTOCOL        *File;\r
1540 \r
1541   Status           = EFI_SUCCESS;\r
1542   File             = NULL;\r
1543 \r
1544   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
1545     return EFI_INVALID_PARAMETER;\r
1546   }\r
1547 \r
1548   Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);\r
1549 \r
1550   mTlsAuthPrivateData = Private;\r
1551 \r
1552   //\r
1553   // Retrieve uncommitted data from Browser\r
1554   //\r
1555   BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);\r
1556   IfrNvData = AllocateZeroPool (BufferSize);\r
1557   if (IfrNvData == NULL) {\r
1558     return EFI_OUT_OF_RESOURCES;\r
1559   }\r
1560 \r
1561   HiiGetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8 *) IfrNvData);\r
1562 \r
1563   if ((Action != EFI_BROWSER_ACTION_CHANGED) &&\r
1564       (Action != EFI_BROWSER_ACTION_CHANGING)) {\r
1565     Status = EFI_UNSUPPORTED;\r
1566     goto EXIT;\r
1567   }\r
1568 \r
1569   if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
1570     switch (QuestionId) {\r
1571     case KEY_TLS_AUTH_CONFIG_CLIENT_CERT:\r
1572     case KEY_TLS_AUTH_CONFIG_SERVER_CA:\r
1573       //\r
1574       // Clear Cert GUID.\r
1575       //\r
1576       ZeroMem (IfrNvData->CertGuid, sizeof (IfrNvData->CertGuid));\r
1577       if (Private->CertGuid == NULL) {\r
1578         Private->CertGuid = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));\r
1579         if (Private->CertGuid == NULL) {\r
1580           return EFI_OUT_OF_RESOURCES;\r
1581         }\r
1582       }\r
1583       if (QuestionId == KEY_TLS_AUTH_CONFIG_CLIENT_CERT) {\r
1584         LabelId = TLS_AUTH_CONFIG_FORMID3_FORM;\r
1585       } else {\r
1586         LabelId = TLS_AUTH_CONFIG_FORMID4_FORM;\r
1587       }\r
1588 \r
1589       //\r
1590       // Refresh selected file.\r
1591       //\r
1592       CleanUpPage (LabelId, Private);\r
1593       break;\r
1594     case KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE:\r
1595       ChooseFile( NULL, NULL, UpdateCAFromFile, &File);\r
1596       break;\r
1597 \r
1598     case KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT:\r
1599       Status = EnrollCertDatabase (Private, EFI_TLS_CA_CERTIFICATE_VARIABLE);\r
1600       if (EFI_ERROR (Status)) {\r
1601         CreatePopUp (\r
1602           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1603           &Key,\r
1604           L"ERROR: Enroll Cert Failure!",\r
1605           NULL\r
1606           );\r
1607       }\r
1608       break;\r
1609 \r
1610     case KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT:\r
1611       if (Private->FileContext->FHandle != NULL) {\r
1612         CloseFile (Private->FileContext->FHandle);\r
1613         Private->FileContext->FHandle = NULL;\r
1614         if (Private->FileContext->FileName!= NULL){\r
1615           FreePool(Private->FileContext->FileName);\r
1616           Private->FileContext->FileName = NULL;\r
1617         }\r
1618       }\r
1619 \r
1620       if (Private->CertGuid!= NULL) {\r
1621         FreePool (Private->CertGuid);\r
1622         Private->CertGuid = NULL;\r
1623       }\r
1624       break;\r
1625 \r
1626     case KEY_TLS_AUTH_CONFIG_DELETE_CERT:\r
1627       UpdateDeletePage (\r
1628         Private,\r
1629         EFI_TLS_CA_CERTIFICATE_VARIABLE,\r
1630         &gEfiTlsCaCertificateGuid,\r
1631         LABEL_CA_DELETE,\r
1632         TLS_AUTH_CONFIG_FORMID5_FORM,\r
1633         OPTION_DEL_CA_ESTION_ID\r
1634         );\r
1635        break;\r
1636 \r
1637     default:\r
1638       if ((QuestionId >= OPTION_DEL_CA_ESTION_ID) &&\r
1639                  (QuestionId < (OPTION_DEL_CA_ESTION_ID + OPTION_CONFIG_RANGE)))  {\r
1640         DeleteCert (\r
1641           Private,\r
1642           EFI_TLS_CA_CERTIFICATE_VARIABLE,\r
1643           &gEfiTlsCaCertificateGuid,\r
1644           LABEL_CA_DELETE,\r
1645           TLS_AUTH_CONFIG_FORMID5_FORM,\r
1646           OPTION_DEL_CA_ESTION_ID,\r
1647           QuestionId - OPTION_DEL_CA_ESTION_ID\r
1648           );\r
1649       }\r
1650       break;\r
1651     }\r
1652   } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
1653     switch (QuestionId) {\r
1654     case KEY_TLS_AUTH_CONFIG_CERT_GUID:\r
1655       ASSERT (Private->CertGuid != NULL);\r
1656       RStatus = StrToGuid (\r
1657                   IfrNvData->CertGuid,\r
1658                   Private->CertGuid\r
1659                   );\r
1660       if (RETURN_ERROR (RStatus) || (IfrNvData->CertGuid[GUID_STRING_LENGTH] != L'\0')) {\r
1661         Status = EFI_INVALID_PARAMETER;\r
1662         break;\r
1663       }\r
1664 \r
1665       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
1666       break;\r
1667     default:\r
1668       break;\r
1669     }\r
1670   }\r
1671 \r
1672 EXIT:\r
1673 \r
1674   if (!EFI_ERROR (Status)) {\r
1675     BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);\r
1676     HiiSetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8*) IfrNvData, NULL);\r
1677   }\r
1678 \r
1679   FreePool (IfrNvData);\r
1680 \r
1681   if (File != NULL){\r
1682     FreePool(File);\r
1683     File = NULL;\r
1684   }\r
1685 \r
1686   return EFI_SUCCESS;\r
1687 \r
1688 }\r
1689 \r