]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/HddPassword/HddPasswordDxe.c
QuarkSocPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / SecurityPkg / HddPassword / HddPasswordDxe.c
CommitLineData
e8959f81
HW
1/** @file\r
2 HDD password driver which is used to support HDD security feature.\r
3\r
4 Copyright (c) 2019, 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\r
8 of the BSD License which accompanies this distribution. The\r
9 full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "HddPasswordDxe.h"\r
18\r
19EFI_GUID mHddPasswordVendorGuid = HDD_PASSWORD_CONFIG_GUID;\r
20CHAR16 mHddPasswordVendorStorageName[] = L"HDD_PASSWORD_CONFIG";\r
21LIST_ENTRY mHddPasswordConfigFormList;\r
22UINT32 mNumberOfHddDevices = 0;\r
23\r
24EFI_GUID mHddPasswordDeviceInfoGuid = HDD_PASSWORD_DEVICE_INFO_GUID;\r
25BOOLEAN mHddPasswordEndOfDxe = FALSE;\r
26HDD_PASSWORD_REQUEST_VARIABLE *mHddPasswordRequestVariable = NULL;\r
27UINTN mHddPasswordRequestVariableSize = 0;\r
28\r
29HII_VENDOR_DEVICE_PATH mHddPasswordHiiVendorDevicePath = {\r
30 {\r
31 {\r
32 HARDWARE_DEVICE_PATH,\r
33 HW_VENDOR_DP,\r
34 {\r
35 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
36 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
37 }\r
38 },\r
39 HDD_PASSWORD_CONFIG_GUID\r
40 },\r
41 {\r
42 END_DEVICE_PATH_TYPE,\r
43 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
44 {\r
45 (UINT8) (END_DEVICE_PATH_LENGTH),\r
46 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
47 }\r
48 }\r
49};\r
50\r
51\r
52/**\r
53 Check if the password is full zero.\r
54\r
55 @param[in] Password Points to the data buffer\r
56\r
57 @retval TRUE This password string is full zero.\r
58 @retval FALSE This password string is not full zero.\r
59\r
60**/\r
61BOOLEAN\r
62PasswordIsFullZero (\r
63 IN CHAR8 *Password\r
64 )\r
65{\r
66 UINTN Index;\r
67\r
68 for (Index = 0; Index < HDD_PASSWORD_MAX_LENGTH; Index++) {\r
69 if (Password[Index] != 0) {\r
70 return FALSE;\r
71 }\r
72 }\r
73\r
74 return TRUE;\r
75}\r
76\r
77/**\r
78 Save device info.\r
79\r
80 @param[in] ConfigFormEntry Points to HDD_PASSWORD_CONFIG_FORM_ENTRY buffer\r
81 @param[in,out] TempDevInfo Points to HDD_PASSWORD_DEVICE_INFO buffer\r
82\r
83**/\r
84VOID\r
85SaveDeviceInfo (\r
86 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
87 IN OUT HDD_PASSWORD_DEVICE_INFO *TempDevInfo\r
88 )\r
89{\r
90 TempDevInfo->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
91 TempDevInfo->Device.Device = (UINT8) ConfigFormEntry->Device;\r
92 TempDevInfo->Device.Function = (UINT8) ConfigFormEntry->Function;\r
93 TempDevInfo->Device.Port = ConfigFormEntry->Port;\r
94 TempDevInfo->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
95 CopyMem (TempDevInfo->Password, ConfigFormEntry->Password, HDD_PASSWORD_MAX_LENGTH);\r
96 TempDevInfo->DevicePathLength = (UINT32) GetDevicePathSize (ConfigFormEntry->DevicePath);\r
97 CopyMem (TempDevInfo->DevicePath, ConfigFormEntry->DevicePath, TempDevInfo->DevicePathLength);\r
98}\r
99\r
100/**\r
101 Build HDD password device info and save them to LockBox.\r
102\r
103 **/\r
104VOID\r
105BuildHddPasswordDeviceInfo (\r
106 VOID\r
107 )\r
108{\r
109 EFI_STATUS Status;\r
110 LIST_ENTRY *Entry;\r
111 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
112 HDD_PASSWORD_DEVICE_INFO *DevInfo;\r
113 HDD_PASSWORD_DEVICE_INFO *TempDevInfo;\r
114 UINTN DevInfoLength;\r
115 UINT8 DummyData;\r
116 BOOLEAN S3InitDevicesExist;\r
117 UINTN S3InitDevicesLength;\r
118 EFI_DEVICE_PATH_PROTOCOL *S3InitDevices;\r
119 EFI_DEVICE_PATH_PROTOCOL *S3InitDevicesBak;\r
120\r
121 //\r
122 // Build HDD password device info and save them to LockBox.\r
123 //\r
124 DevInfoLength = 0;\r
125 EFI_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
126 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
127\r
128 //\r
129 // 1. Handle device which already set password.\r
130 // 2. When request to send freeze comamnd, driver also needs to handle device\r
131 // which support security feature.\r
132 //\r
133 if ((!PasswordIsFullZero (ConfigFormEntry->Password)) ||\r
134 ((ConfigFormEntry->IfrData.SecurityStatus.Supported != 0) &&\r
135 (ConfigFormEntry->IfrData.SecurityStatus.Enabled == 0))) {\r
136 DevInfoLength += sizeof (HDD_PASSWORD_DEVICE_INFO) +\r
137 GetDevicePathSize (ConfigFormEntry->DevicePath);\r
138 }\r
139 }\r
140\r
141 if (DevInfoLength == 0) {\r
142 return;\r
143 }\r
144\r
145 S3InitDevicesLength = sizeof (DummyData);\r
146 Status = RestoreLockBox (\r
147 &gS3StorageDeviceInitListGuid,\r
148 &DummyData,\r
149 &S3InitDevicesLength\r
150 );\r
151 ASSERT ((Status == EFI_NOT_FOUND) || (Status == EFI_BUFFER_TOO_SMALL));\r
152 if (Status == EFI_NOT_FOUND) {\r
153 S3InitDevices = NULL;\r
154 S3InitDevicesExist = FALSE;\r
155 } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
156 S3InitDevices = AllocatePool (S3InitDevicesLength);\r
157 ASSERT (S3InitDevices != NULL);\r
158\r
159 Status = RestoreLockBox (\r
160 &gS3StorageDeviceInitListGuid,\r
161 S3InitDevices,\r
162 &S3InitDevicesLength\r
163 );\r
164 ASSERT_EFI_ERROR (Status);\r
165 S3InitDevicesExist = TRUE;\r
166 } else {\r
167 return;\r
168 }\r
169\r
170 DevInfo = AllocateZeroPool (DevInfoLength);\r
171 ASSERT (DevInfo != NULL);\r
172\r
173 TempDevInfo = DevInfo;\r
174 EFI_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
175 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
176\r
177 if ((!PasswordIsFullZero (ConfigFormEntry->Password)) ||\r
178 ((ConfigFormEntry->IfrData.SecurityStatus.Supported != 0) &&\r
179 (ConfigFormEntry->IfrData.SecurityStatus.Enabled == 0))) {\r
180 SaveDeviceInfo (ConfigFormEntry, TempDevInfo);\r
181\r
182 S3InitDevicesBak = S3InitDevices;\r
183 S3InitDevices = AppendDevicePathInstance (\r
184 S3InitDevicesBak,\r
185 ConfigFormEntry->DevicePath\r
186 );\r
187 if (S3InitDevicesBak != NULL) {\r
188 FreePool (S3InitDevicesBak);\r
189 }\r
190 ASSERT (S3InitDevices != NULL);\r
191\r
192 TempDevInfo = (HDD_PASSWORD_DEVICE_INFO *) ((UINTN)TempDevInfo +\r
193 sizeof (HDD_PASSWORD_DEVICE_INFO) +\r
194 TempDevInfo->DevicePathLength);\r
195 }\r
196 }\r
197\r
198 Status = SaveLockBox (\r
199 &mHddPasswordDeviceInfoGuid,\r
200 DevInfo,\r
201 DevInfoLength\r
202 );\r
203 ASSERT_EFI_ERROR (Status);\r
204\r
205 Status = SetLockBoxAttributes (\r
206 &mHddPasswordDeviceInfoGuid,\r
207 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
208 );\r
209 ASSERT_EFI_ERROR (Status);\r
210\r
211 S3InitDevicesLength = GetDevicePathSize (S3InitDevices);\r
212 if (S3InitDevicesExist) {\r
213 Status = UpdateLockBox (\r
214 &gS3StorageDeviceInitListGuid,\r
215 0,\r
216 S3InitDevices,\r
217 S3InitDevicesLength\r
218 );\r
219 ASSERT_EFI_ERROR (Status);\r
220 } else {\r
221 Status = SaveLockBox (\r
222 &gS3StorageDeviceInitListGuid,\r
223 S3InitDevices,\r
224 S3InitDevicesLength\r
225 );\r
226 ASSERT_EFI_ERROR (Status);\r
227\r
228 Status = SetLockBoxAttributes (\r
229 &gS3StorageDeviceInitListGuid,\r
230 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
231 );\r
232 ASSERT_EFI_ERROR (Status);\r
233 }\r
234\r
235 ZeroMem (DevInfo, DevInfoLength);\r
236 FreePool (DevInfo);\r
237 FreePool (S3InitDevices);\r
238}\r
239\r
240/**\r
241 Send freeze lock cmd through Ata Pass Thru Protocol.\r
242\r
243 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
244 @param[in] Port The port number of the ATA device to send the command.\r
245 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
246 If there is no port multiplier, then specify 0xFFFF.\r
247\r
248 @retval EFI_SUCCESS Successful to send freeze lock cmd.\r
249 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
250 @retval EFI_OUT_OF_RESOURCES Not enough memory to send freeze lock cmd.\r
251 @retval EFI_DEVICE_ERROR Can not send freeze lock cmd.\r
252\r
253**/\r
254EFI_STATUS\r
255FreezeLockDevice (\r
256 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
257 IN UINT16 Port,\r
258 IN UINT16 PortMultiplierPort\r
259 )\r
260{\r
261 EFI_STATUS Status;\r
262 EFI_ATA_COMMAND_BLOCK Acb;\r
263 EFI_ATA_STATUS_BLOCK *Asb;\r
264 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
265\r
266 if (AtaPassThru == NULL) {\r
267 return EFI_INVALID_PARAMETER;\r
268 }\r
269\r
270 //\r
271 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
272 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
273 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
274 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
275 // may not be aligned when allocated on stack for some compilers. Hence, we\r
276 // use the API AllocateAlignedPages to ensure this structure is properly\r
277 // aligned.\r
278 //\r
279 Asb = AllocateAlignedPages (\r
280 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
281 AtaPassThru->Mode->IoAlign\r
282 );\r
283 if (Asb == NULL) {\r
284 return EFI_OUT_OF_RESOURCES;\r
285 }\r
286\r
287 //\r
288 // Prepare for ATA command block.\r
289 //\r
290 ZeroMem (&Acb, sizeof (Acb));\r
291 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
292 Acb.AtaCommand = ATA_SECURITY_FREEZE_LOCK_CMD;\r
293 Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));\r
294\r
295 //\r
296 // Prepare for ATA pass through packet.\r
297 //\r
298 ZeroMem (&Packet, sizeof (Packet));\r
299 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA;\r
300 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_NO_DATA_TRANSFER;\r
301 Packet.Asb = Asb;\r
302 Packet.Acb = &Acb;\r
303 Packet.Timeout = ATA_TIMEOUT;\r
304\r
305 Status = AtaPassThru->PassThru (\r
306 AtaPassThru,\r
307 Port,\r
308 PortMultiplierPort,\r
309 &Packet,\r
310 NULL\r
311 );\r
312 if (!EFI_ERROR (Status) &&\r
313 ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&\r
314 ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {\r
315 Status = EFI_DEVICE_ERROR;\r
316 }\r
317\r
318 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
319\r
320 DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));\r
321 return Status;\r
322}\r
323\r
324/**\r
325 Get attached harddisk identify data through Ata Pass Thru Protocol.\r
326\r
327 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
328 @param[in] Port The port number of the ATA device to send the command.\r
329 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
330 If there is no port multiplier, then specify 0xFFFF.\r
331 @param[in] IdentifyData The buffer to store identify data.\r
332\r
333 @retval EFI_SUCCESS Successful to get identify data.\r
334 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
335 @retval EFI_OUT_OF_RESOURCES Not enough memory to get identify data.\r
336 @retval EFI_DEVICE_ERROR Can not get identify data.\r
337\r
338**/\r
339EFI_STATUS\r
340GetHddDeviceIdentifyData (\r
341 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
342 IN UINT16 Port,\r
343 IN UINT16 PortMultiplierPort,\r
344 IN ATA_IDENTIFY_DATA *IdentifyData\r
345 )\r
346{\r
347 EFI_STATUS Status;\r
348 EFI_ATA_COMMAND_BLOCK Acb;\r
349 EFI_ATA_STATUS_BLOCK *Asb;\r
350 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
351\r
352 if ((AtaPassThru == NULL) || (IdentifyData == NULL)) {\r
353 return EFI_INVALID_PARAMETER;\r
354 }\r
355\r
356 //\r
357 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
358 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
359 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
360 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
361 // may not be aligned when allocated on stack for some compilers. Hence, we\r
362 // use the API AllocateAlignedPages to ensure this structure is properly\r
363 // aligned.\r
364 //\r
365 Asb = AllocateAlignedPages (\r
366 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
367 AtaPassThru->Mode->IoAlign\r
368 );\r
369 if (Asb == NULL) {\r
370 return EFI_OUT_OF_RESOURCES;\r
371 }\r
372\r
373 //\r
374 // Prepare for ATA command block.\r
375 //\r
376 ZeroMem (&Acb, sizeof (Acb));\r
377 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
378 Acb.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
379 Acb.AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4)));\r
380\r
381 //\r
382 // Prepare for ATA pass through packet.\r
383 //\r
384 ZeroMem (&Packet, sizeof (Packet));\r
385 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;\r
386 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
387 Packet.Asb = Asb;\r
388 Packet.Acb = &Acb;\r
389 Packet.InDataBuffer = IdentifyData;\r
390 Packet.InTransferLength = sizeof (ATA_IDENTIFY_DATA);\r
391 Packet.Timeout = ATA_TIMEOUT;\r
392\r
393 Status = AtaPassThru->PassThru (\r
394 AtaPassThru,\r
395 Port,\r
396 PortMultiplierPort,\r
397 &Packet,\r
398 NULL\r
399 );\r
400\r
401 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
402\r
403 return Status;\r
404}\r
405\r
406/**\r
407 Parse security status according to identify data.\r
408\r
409 @param[in] IdentifyData The buffer to store identify data.\r
410 @param[in, out] IfrData IFR data to hold security status.\r
411\r
412**/\r
413VOID\r
414GetHddPasswordSecurityStatus (\r
415 IN ATA_IDENTIFY_DATA *IdentifyData,\r
416 IN OUT HDD_PASSWORD_CONFIG *IfrData\r
417 )\r
418{\r
419 IfrData->SecurityStatus.Supported = (IdentifyData->command_set_supported_82 & BIT1) ? 1 : 0;\r
420 IfrData->SecurityStatus.Enabled = (IdentifyData->security_status & BIT1) ? 1 : 0;\r
421 IfrData->SecurityStatus.Locked = (IdentifyData->security_status & BIT2) ? 1 : 0;\r
422 IfrData->SecurityStatus.Frozen = (IdentifyData->security_status & BIT3) ? 1 : 0;\r
423 IfrData->SecurityStatus.UserPasswordStatus = IfrData->SecurityStatus.Enabled;\r
424 IfrData->SecurityStatus.MasterPasswordStatus = IfrData->SecurityStatus.Supported;\r
425\r
426 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Supported = %x\n", IfrData->SecurityStatus.Supported));\r
427 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Enabled = %x\n", IfrData->SecurityStatus.Enabled));\r
428 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Locked = %x\n", IfrData->SecurityStatus.Locked));\r
429 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Frozen = %x\n", IfrData->SecurityStatus.Frozen));\r
430 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.UserPasswordStatus = %x\n", IfrData->SecurityStatus.UserPasswordStatus));\r
431 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.MasterPasswordStatus = %x\n", IfrData->SecurityStatus.MasterPasswordStatus));\r
432}\r
433\r
434/**\r
435 Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
436\r
437 This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
438\r
439 @param Event Event whose notification function is being invoked.\r
440 @param Context Pointer to the notification function's context.\r
441\r
442**/\r
443VOID\r
444EFIAPI\r
445HddPasswordEndOfDxeEventNotify (\r
446 EFI_EVENT Event,\r
447 VOID *Context\r
448 )\r
449{\r
450 LIST_ENTRY *Entry;\r
451 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
452 EFI_STATUS Status;\r
453 ATA_IDENTIFY_DATA IdentifyData;\r
454\r
455 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
456\r
457 mHddPasswordEndOfDxe = TRUE;\r
458\r
459 if (mHddPasswordRequestVariable != NULL) {\r
460 //\r
461 // Free the HDD password request variable buffer here\r
462 // as the HDD password requests should have been processed.\r
463 //\r
464 FreePool (mHddPasswordRequestVariable);\r
465 mHddPasswordRequestVariable = NULL;\r
466 mHddPasswordRequestVariableSize = 0;\r
467 }\r
468\r
469 //\r
470 // If no any device, return directly.\r
471 //\r
472 if (IsListEmpty (&mHddPasswordConfigFormList)) {\r
473 gBS->CloseEvent (Event);\r
474 return;\r
475 }\r
476\r
477 BuildHddPasswordDeviceInfo ();\r
478\r
479 //\r
480 // Zero passsword and freeze lock device.\r
481 //\r
482 EFI_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
483 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
484\r
485 ZeroMem (ConfigFormEntry->Password, HDD_PASSWORD_MAX_LENGTH);\r
486\r
487 //\r
488 // Check whether need send freeze lock command.\r
489 // Below device will be froze:\r
490 // 1. Device not enable password.\r
491 // 2. Device enable password and unlocked.\r
492 //\r
493 if ((ConfigFormEntry->IfrData.SecurityStatus.Supported != 0) &&\r
494 (ConfigFormEntry->IfrData.SecurityStatus.Locked == 0) &&\r
495 (ConfigFormEntry->IfrData.SecurityStatus.Frozen == 0)) {\r
496 Status = FreezeLockDevice (ConfigFormEntry->AtaPassThru, ConfigFormEntry->Port, ConfigFormEntry->PortMultiplierPort);\r
497 DEBUG ((DEBUG_INFO, "FreezeLockDevice return %r!\n", Status));\r
498 Status = GetHddDeviceIdentifyData (\r
499 ConfigFormEntry->AtaPassThru,\r
500 ConfigFormEntry->Port,\r
501 ConfigFormEntry->PortMultiplierPort,\r
502 &IdentifyData\r
503 );\r
504 GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);\r
505 }\r
506 }\r
507\r
508 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
509\r
510 gBS->CloseEvent (Event);\r
511}\r
512\r
513/**\r
514 Generate Salt value.\r
515\r
516 @param[in, out] SaltValue Points to the salt buffer, 32 bytes\r
517\r
518**/\r
519VOID\r
520GenSalt (\r
521 IN OUT UINT8 *SaltValue\r
522 )\r
523{\r
524 RandomSeed (NULL, 0);\r
525 RandomBytes (SaltValue, PASSWORD_SALT_SIZE);\r
526}\r
527\r
528/**\r
529 Hash the data to get credential.\r
530\r
531 @param[in] Buffer Points to the data buffer\r
532 @param[in] BufferSize Buffer size\r
533 @param[in] SaltValue Points to the salt buffer, 32 bytes\r
534 @param[out] Credential Points to the hashed result\r
535\r
536 @retval TRUE Hash the data successfully.\r
537 @retval FALSE Failed to hash the data.\r
538\r
539**/\r
540BOOLEAN\r
541GenerateCredential (\r
542 IN UINT8 *Buffer,\r
543 IN UINTN BufferSize,\r
544 IN UINT8 *SaltValue,\r
545 OUT UINT8 *Credential\r
546 )\r
547{\r
548 BOOLEAN Status;\r
549 UINTN HashSize;\r
550 VOID *Hash;\r
551 VOID *HashData;\r
552\r
553 Hash = NULL;\r
554 HashData = NULL;\r
555 Status = FALSE;\r
556\r
557 HashSize = Sha256GetContextSize ();\r
558 Hash = AllocateZeroPool (HashSize);\r
559 ASSERT (Hash != NULL);\r
560 if (Hash == NULL) {\r
561 goto Done;\r
562 }\r
563\r
564 Status = Sha256Init (Hash);\r
565 if (!Status) {\r
566 goto Done;\r
567 }\r
568\r
569 HashData = AllocateZeroPool (PASSWORD_SALT_SIZE + BufferSize);\r
570 ASSERT (HashData != NULL);\r
571 if (HashData == NULL) {\r
572 goto Done;\r
573 }\r
574\r
575 CopyMem (HashData, SaltValue, PASSWORD_SALT_SIZE);\r
576 CopyMem ((UINT8 *) HashData + PASSWORD_SALT_SIZE, Buffer, BufferSize);\r
577\r
578 Status = Sha256Update (Hash, HashData, PASSWORD_SALT_SIZE + BufferSize);\r
579 if (!Status) {\r
580 goto Done;\r
581 }\r
582\r
583 Status = Sha256Final (Hash, Credential);\r
584\r
585Done:\r
586 if (Hash != NULL) {\r
587 FreePool (Hash);\r
588 }\r
589 if (HashData != NULL) {\r
590 ZeroMem (HashData, PASSWORD_SALT_SIZE + BufferSize);\r
591 FreePool (HashData);\r
592 }\r
593 return Status;\r
594}\r
595\r
596/**\r
597 Save HDD password variable that will be used to validate HDD password\r
598 when the device is at frozen state.\r
599\r
600 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
601 @param[in] Password The hdd password of attached ATA device.\r
602\r
603**/\r
604VOID\r
605SaveHddPasswordVariable (\r
606 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
607 IN CHAR8 *Password\r
608 )\r
609{\r
610 EFI_STATUS Status;\r
611 HDD_PASSWORD_VARIABLE *TempVariable;\r
612 UINTN TempVariableSize;\r
613 HDD_PASSWORD_VARIABLE *NextNode;\r
614 HDD_PASSWORD_VARIABLE *Variable;\r
615 UINTN VariableSize;\r
616 HDD_PASSWORD_VARIABLE *NewVariable;\r
617 UINTN NewVariableSize;\r
618 BOOLEAN Delete;\r
619 BOOLEAN HashOk;\r
620 UINT8 HashData[SHA256_DIGEST_SIZE];\r
621 UINT8 SaltData[PASSWORD_SALT_SIZE];\r
622\r
623 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
624\r
625 Delete = FALSE;\r
626 if (!PasswordIsFullZero (Password)) {\r
627 //\r
628 // It is Set/Update HDD Password.\r
629 //\r
630 ZeroMem (HashData, sizeof (HashData));\r
631 ZeroMem (SaltData, sizeof (SaltData));\r
632 GenSalt (SaltData);\r
633 HashOk = GenerateCredential ((UINT8 *) Password, HDD_PASSWORD_MAX_LENGTH, SaltData, HashData);\r
634 if (!HashOk) {\r
635 DEBUG ((DEBUG_INFO, "GenerateCredential failed\n"));\r
636 return;\r
637 }\r
638 } else {\r
639 //\r
640 // It is Disable HDD Password.\r
641 // Go to delete the variable node for the HDD password device.\r
642 //\r
643 Delete = TRUE;\r
644 }\r
645\r
646 Variable = NULL;\r
647 VariableSize = 0;\r
648 NewVariable = NULL;\r
649 NewVariableSize = 0;\r
650\r
651 Status = GetVariable2 (\r
652 HDD_PASSWORD_VARIABLE_NAME,\r
653 &mHddPasswordVendorGuid,\r
654 (VOID **) &Variable,\r
655 &VariableSize\r
656 );\r
657 if (Delete) {\r
658 if (!EFI_ERROR (Status) && (Variable != NULL)) {\r
659 TempVariable = Variable;\r
660 TempVariableSize = VariableSize;\r
661 while (TempVariableSize >= sizeof (HDD_PASSWORD_VARIABLE)) {\r
662 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
663 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
664 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
665 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
666 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
667 //\r
668 // Found the node for the HDD password device.\r
669 // Delete the node.\r
670 //\r
671 NextNode = TempVariable + 1;\r
672 CopyMem (TempVariable, NextNode, (UINTN) Variable + VariableSize - (UINTN) NextNode);\r
673 NewVariable = Variable;\r
674 NewVariableSize = VariableSize - sizeof (HDD_PASSWORD_VARIABLE);\r
675 break;\r
676 }\r
677 TempVariableSize -= sizeof (HDD_PASSWORD_VARIABLE);\r
678 TempVariable += 1;\r
679 }\r
680 if (NewVariable == NULL) {\r
681 DEBUG ((DEBUG_INFO, "The variable node for the HDD password device is not found\n"));\r
682 }\r
683 } else {\r
684 DEBUG ((DEBUG_INFO, "HddPassword variable get failed (%r)\n", Status));\r
685 }\r
686 } else {\r
687 if (!EFI_ERROR (Status) && (Variable != NULL)) {\r
688 TempVariable = Variable;\r
689 TempVariableSize = VariableSize;\r
690 while (TempVariableSize >= sizeof (HDD_PASSWORD_VARIABLE)) {\r
691 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
692 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
693 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
694 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
695 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
696 //\r
697 // Found the node for the HDD password device.\r
698 // Update the node.\r
699 //\r
700 CopyMem (TempVariable->PasswordHash, HashData, sizeof (HashData));\r
701 CopyMem (TempVariable->PasswordSalt, SaltData, sizeof (SaltData));\r
702 NewVariable = Variable;\r
703 NewVariableSize = VariableSize;\r
704 break;\r
705 }\r
706 TempVariableSize -= sizeof (HDD_PASSWORD_VARIABLE);\r
707 TempVariable += 1;\r
708 }\r
709 if (NewVariable == NULL) {\r
710 //\r
711 // The node for the HDD password device is not found.\r
712 // Create node for the HDD password device.\r
713 //\r
714 NewVariableSize = VariableSize + sizeof (HDD_PASSWORD_VARIABLE);\r
715 NewVariable = AllocateZeroPool (NewVariableSize);\r
716 ASSERT (NewVariable != NULL);\r
717 CopyMem (NewVariable, Variable, VariableSize);\r
718 TempVariable = (HDD_PASSWORD_VARIABLE *) ((UINTN) NewVariable + VariableSize);\r
719 TempVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
720 TempVariable->Device.Device = (UINT8) ConfigFormEntry->Device;\r
721 TempVariable->Device.Function = (UINT8) ConfigFormEntry->Function;\r
722 TempVariable->Device.Port = ConfigFormEntry->Port;\r
723 TempVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
724 CopyMem (TempVariable->PasswordHash, HashData, sizeof (HashData));\r
725 CopyMem (TempVariable->PasswordSalt, SaltData, sizeof (SaltData));\r
726 }\r
727 } else {\r
728 NewVariableSize = sizeof (HDD_PASSWORD_VARIABLE);\r
729 NewVariable = AllocateZeroPool (NewVariableSize);\r
730 ASSERT (NewVariable != NULL);\r
731 NewVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
732 NewVariable->Device.Device = (UINT8) ConfigFormEntry->Device;\r
733 NewVariable->Device.Function = (UINT8) ConfigFormEntry->Function;\r
734 NewVariable->Device.Port = ConfigFormEntry->Port;\r
735 NewVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
736 CopyMem (NewVariable->PasswordHash, HashData, sizeof (HashData));\r
737 CopyMem (NewVariable->PasswordSalt, SaltData, sizeof (SaltData));\r
738 }\r
739 }\r
740\r
741 if (NewVariable != NULL) {\r
742 Status = gRT->SetVariable (\r
743 HDD_PASSWORD_VARIABLE_NAME,\r
744 &mHddPasswordVendorGuid,\r
745 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
746 NewVariableSize,\r
747 NewVariable\r
748 );\r
749 if (EFI_ERROR (Status)) {\r
750 DEBUG ((DEBUG_INFO, "HddPassword variable set failed (%r)\n", Status));\r
751 }\r
752 }\r
753\r
754 if (NewVariable != Variable) {\r
755 FreePool (NewVariable);\r
756 }\r
757 if (Variable != NULL) {\r
758 FreePool (Variable);\r
759 }\r
760\r
761 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
762}\r
763\r
764/**\r
765 Get saved HDD password variable that will be used to validate HDD password\r
766 when the device is at frozen state.\r
767\r
768 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
769 @param[out] HddPasswordVariable The variable node for the HDD password device.\r
770\r
771 @retval TRUE The variable node for the HDD password device is found and returned.\r
772 @retval FALSE The variable node for the HDD password device is not found.\r
773\r
774**/\r
775BOOLEAN\r
776GetSavedHddPasswordVariable (\r
777 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
778 OUT HDD_PASSWORD_VARIABLE *HddPasswordVariable\r
779 )\r
780{\r
781 EFI_STATUS Status;\r
782 HDD_PASSWORD_VARIABLE *TempVariable;\r
783 HDD_PASSWORD_VARIABLE *Variable;\r
784 UINTN VariableSize;\r
785 BOOLEAN Found;\r
786\r
787 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
788\r
789 Variable = NULL;\r
790 VariableSize = 0;\r
791\r
792 Status = GetVariable2 (\r
793 HDD_PASSWORD_VARIABLE_NAME,\r
794 &mHddPasswordVendorGuid,\r
795 (VOID **) &Variable,\r
796 &VariableSize\r
797 );\r
798 if (EFI_ERROR (Status) || (Variable == NULL)) {\r
799 DEBUG ((DEBUG_INFO, "HddPassword variable get failed (%r)\n", Status));\r
800 return FALSE;\r
801 }\r
802\r
803 Found = FALSE;\r
804 TempVariable = Variable;\r
805 while (VariableSize >= sizeof (HDD_PASSWORD_VARIABLE)) {\r
806 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
807 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
808 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
809 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
810 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
811 //\r
812 // Found the node for the HDD password device.\r
813 // Get the node.\r
814 //\r
815 CopyMem (HddPasswordVariable, TempVariable, sizeof (HDD_PASSWORD_VARIABLE));\r
816 Found = TRUE;\r
817 break;\r
818 }\r
819 VariableSize -= sizeof (HDD_PASSWORD_VARIABLE);\r
820 TempVariable += 1;\r
821 }\r
822\r
823 FreePool (Variable);\r
824\r
825 if (!Found) {\r
826 DEBUG ((DEBUG_INFO, "The variable node for the HDD password device is not found\n"));\r
827 }\r
828\r
829 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
830\r
831 return Found;\r
832}\r
833\r
834/**\r
835 Use saved HDD password variable to validate HDD password\r
836 when the device is at frozen state.\r
837\r
838 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
839 @param[in] Password The hdd password of attached ATA device.\r
840\r
841 @retval EFI_SUCCESS Pass to validate the HDD password.\r
842 @retval EFI_NOT_FOUND The variable node for the HDD password device is not found.\r
843 @retval EFI_DEVICE_ERROR Failed to generate credential for the HDD password.\r
844 @retval EFI_INVALID_PARAMETER Failed to validate the HDD password.\r
845\r
846**/\r
847EFI_STATUS\r
848ValidateHddPassword (\r
849 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
850 IN CHAR8 *Password\r
851 )\r
852{\r
853 EFI_STATUS Status;\r
854 HDD_PASSWORD_VARIABLE HddPasswordVariable;\r
855 BOOLEAN HashOk;\r
856 UINT8 HashData[SHA256_DIGEST_SIZE];\r
857\r
858 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
859\r
860 if (!GetSavedHddPasswordVariable (ConfigFormEntry, &HddPasswordVariable)) {\r
861 DEBUG ((DEBUG_INFO, "GetSavedHddPasswordVariable failed\n"));\r
862 return EFI_NOT_FOUND;\r
863 }\r
864\r
865 ZeroMem (HashData, sizeof (HashData));\r
866 HashOk = GenerateCredential ((UINT8 *) Password, HDD_PASSWORD_MAX_LENGTH, HddPasswordVariable.PasswordSalt, HashData);\r
867 if (!HashOk) {\r
868 DEBUG ((DEBUG_INFO, "GenerateCredential failed\n"));\r
869 return EFI_DEVICE_ERROR;\r
870 }\r
871\r
872 if (CompareMem (HddPasswordVariable.PasswordHash, HashData, sizeof (HashData)) != 0) {\r
873 Status = EFI_INVALID_PARAMETER;\r
874 } else {\r
875 Status = EFI_SUCCESS;\r
876 }\r
877\r
878 DEBUG ((DEBUG_INFO, "%a() - exit (%r)\n", __FUNCTION__, Status));\r
879 return Status;\r
880}\r
881\r
882/**\r
883 Send unlock hdd password cmd through Ata Pass Thru Protocol.\r
884\r
885 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
886 @param[in] Port The port number of the ATA device to send the command.\r
887 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
888 If there is no port multiplier, then specify 0xFFFF.\r
889 @param[in] Identifier The identifier to set user or master password.\r
890 @param[in] Password The hdd password of attached ATA device.\r
891\r
892 @retval EFI_SUCCESS Successful to send unlock hdd password cmd.\r
893 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
894 @retval EFI_OUT_OF_RESOURCES Not enough memory to send unlock hdd password cmd.\r
895 @retval EFI_DEVICE_ERROR Can not send unlock hdd password cmd.\r
896\r
897**/\r
898EFI_STATUS\r
899UnlockHddPassword (\r
900 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
901 IN UINT16 Port,\r
902 IN UINT16 PortMultiplierPort,\r
903 IN CHAR8 Identifier,\r
904 IN CHAR8 *Password\r
905 )\r
906{\r
907 EFI_STATUS Status;\r
908 EFI_ATA_COMMAND_BLOCK Acb;\r
909 EFI_ATA_STATUS_BLOCK *Asb;\r
910 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
911 UINT8 Buffer[HDD_PAYLOAD];\r
912\r
913 if ((AtaPassThru == NULL) || (Password == NULL)) {\r
914 return EFI_INVALID_PARAMETER;\r
915 }\r
916\r
917 //\r
918 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
919 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
920 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
921 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
922 // may not be aligned when allocated on stack for some compilers. Hence, we\r
923 // use the API AllocateAlignedPages to ensure this structure is properly\r
924 // aligned.\r
925 //\r
926 Asb = AllocateAlignedPages (\r
927 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
928 AtaPassThru->Mode->IoAlign\r
929 );\r
930 if (Asb == NULL) {\r
931 return EFI_OUT_OF_RESOURCES;\r
932 }\r
933\r
934 //\r
935 // Prepare for ATA command block.\r
936 //\r
937 ZeroMem (&Acb, sizeof (Acb));\r
938 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
939 Acb.AtaCommand = ATA_SECURITY_UNLOCK_CMD;\r
940 Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));\r
941\r
942 //\r
943 // Prepare for ATA pass through packet.\r
944 //\r
945 ZeroMem (&Packet, sizeof (Packet));\r
946 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT;\r
947 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;\r
948 Packet.Asb = Asb;\r
949 Packet.Acb = &Acb;\r
950\r
951 ((CHAR16 *) Buffer)[0] = Identifier & BIT0;\r
952 CopyMem (&((CHAR16 *) Buffer)[1], Password, HDD_PASSWORD_MAX_LENGTH);\r
953\r
954 Packet.OutDataBuffer = Buffer;\r
955 Packet.OutTransferLength = sizeof (Buffer);\r
956 Packet.Timeout = ATA_TIMEOUT;\r
957\r
958 Status = AtaPassThru->PassThru (\r
959 AtaPassThru,\r
960 Port,\r
961 PortMultiplierPort,\r
962 &Packet,\r
963 NULL\r
964 );\r
965 if (!EFI_ERROR (Status) &&\r
966 ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&\r
967 ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {\r
968 Status = EFI_DEVICE_ERROR;\r
969 }\r
970\r
971 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
972\r
973 ZeroMem (Buffer, sizeof (Buffer));\r
974\r
975 DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));\r
976 return Status;\r
977}\r
978\r
979/**\r
980 Send disable hdd password cmd through Ata Pass Thru Protocol.\r
981\r
982 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
983 @param[in] Port The port number of the ATA device to send the command.\r
984 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
985 If there is no port multiplier, then specify 0xFFFF.\r
986 @param[in] Identifier The identifier to set user or master password.\r
987 @param[in] Password The hdd password of attached ATA device.\r
988\r
989 @retval EFI_SUCCESS Successful to disable hdd password cmd.\r
990 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
991 @retval EFI_OUT_OF_RESOURCES Not enough memory to disable hdd password cmd.\r
992 @retval EFI_DEVICE_ERROR Can not disable hdd password cmd.\r
993\r
994**/\r
995EFI_STATUS\r
996DisableHddPassword (\r
997 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
998 IN UINT16 Port,\r
999 IN UINT16 PortMultiplierPort,\r
1000 IN CHAR8 Identifier,\r
1001 IN CHAR8 *Password\r
1002 )\r
1003{\r
1004 EFI_STATUS Status;\r
1005 EFI_ATA_COMMAND_BLOCK Acb;\r
1006 EFI_ATA_STATUS_BLOCK *Asb;\r
1007 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
1008 UINT8 Buffer[HDD_PAYLOAD];\r
1009\r
1010 if ((AtaPassThru == NULL) || (Password == NULL)) {\r
1011 return EFI_INVALID_PARAMETER;\r
1012 }\r
1013\r
1014 //\r
1015 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
1016 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
1017 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
1018 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
1019 // may not be aligned when allocated on stack for some compilers. Hence, we\r
1020 // use the API AllocateAlignedPages to ensure this structure is properly\r
1021 // aligned.\r
1022 //\r
1023 Asb = AllocateAlignedPages (\r
1024 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
1025 AtaPassThru->Mode->IoAlign\r
1026 );\r
1027 if (Asb == NULL) {\r
1028 return EFI_OUT_OF_RESOURCES;\r
1029 }\r
1030\r
1031 //\r
1032 // Prepare for ATA command block.\r
1033 //\r
1034 ZeroMem (&Acb, sizeof (Acb));\r
1035 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
1036 Acb.AtaCommand = ATA_SECURITY_DIS_PASSWORD_CMD;\r
1037 Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));\r
1038\r
1039 //\r
1040 // Prepare for ATA pass through packet.\r
1041 //\r
1042 ZeroMem (&Packet, sizeof (Packet));\r
1043 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT;\r
1044 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;\r
1045 Packet.Asb = Asb;\r
1046 Packet.Acb = &Acb;\r
1047\r
1048 ((CHAR16 *) Buffer)[0] = Identifier & BIT0;\r
1049 CopyMem (&((CHAR16 *) Buffer)[1], Password, HDD_PASSWORD_MAX_LENGTH);\r
1050\r
1051 Packet.OutDataBuffer = Buffer;\r
1052 Packet.OutTransferLength = sizeof (Buffer);\r
1053 Packet.Timeout = ATA_TIMEOUT;\r
1054\r
1055 Status = AtaPassThru->PassThru (\r
1056 AtaPassThru,\r
1057 Port,\r
1058 PortMultiplierPort,\r
1059 &Packet,\r
1060 NULL\r
1061 );\r
1062 if (!EFI_ERROR (Status) &&\r
1063 ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&\r
1064 ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {\r
1065 Status = EFI_DEVICE_ERROR;\r
1066 }\r
1067\r
1068 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
1069\r
1070 ZeroMem (Buffer, sizeof (Buffer));\r
1071\r
1072 DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));\r
1073 return Status;\r
1074}\r
1075\r
1076/**\r
1077 Send set hdd password cmd through Ata Pass Thru Protocol.\r
1078\r
1079 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
1080 @param[in] Port The port number of the ATA device to send the command.\r
1081 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
1082 If there is no port multiplier, then specify 0xFFFF.\r
1083 @param[in] Identifier The identifier to set user or master password.\r
1084 @param[in] SecurityLevel The security level to be set to device.\r
1085 @param[in] MasterPasswordIdentifier The master password identifier to be set to device.\r
1086 @param[in] Password The hdd password of attached ATA device.\r
1087\r
1088 @retval EFI_SUCCESS Successful to set hdd password cmd.\r
1089 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
1090 @retval EFI_OUT_OF_RESOURCES Not enough memory to set hdd password cmd.\r
1091 @retval EFI_DEVICE_ERROR Can not set hdd password cmd.\r
1092\r
1093**/\r
1094EFI_STATUS\r
1095SetHddPassword (\r
1096 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1097 IN UINT16 Port,\r
1098 IN UINT16 PortMultiplierPort,\r
1099 IN CHAR8 Identifier,\r
1100 IN CHAR8 SecurityLevel,\r
1101 IN CHAR16 MasterPasswordIdentifier,\r
1102 IN CHAR8 *Password\r
1103 )\r
1104{\r
1105 EFI_STATUS Status;\r
1106 EFI_ATA_COMMAND_BLOCK Acb;\r
1107 EFI_ATA_STATUS_BLOCK *Asb;\r
1108 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
1109 UINT8 Buffer[HDD_PAYLOAD];\r
1110\r
1111 if ((AtaPassThru == NULL) || (Password == NULL)) {\r
1112 return EFI_INVALID_PARAMETER;\r
1113 }\r
1114\r
1115 //\r
1116 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
1117 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
1118 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
1119 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
1120 // may not be aligned when allocated on stack for some compilers. Hence, we\r
1121 // use the API AllocateAlignedPages to ensure this structure is properly\r
1122 // aligned.\r
1123 //\r
1124 Asb = AllocateAlignedPages (\r
1125 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
1126 AtaPassThru->Mode->IoAlign\r
1127 );\r
1128 if (Asb == NULL) {\r
1129 return EFI_OUT_OF_RESOURCES;\r
1130 }\r
1131\r
1132 //\r
1133 // Prepare for ATA command block.\r
1134 //\r
1135 ZeroMem (&Acb, sizeof (Acb));\r
1136 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
1137 Acb.AtaCommand = ATA_SECURITY_SET_PASSWORD_CMD;\r
1138 Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));\r
1139\r
1140 //\r
1141 // Prepare for ATA pass through packet.\r
1142 //\r
1143 ZeroMem (&Packet, sizeof (Packet));\r
1144 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT;\r
1145 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;\r
1146 Packet.Asb = Asb;\r
1147 Packet.Acb = &Acb;\r
1148\r
1149 ((CHAR16 *) Buffer)[0] = (Identifier | (UINT16)(SecurityLevel << 8)) & (BIT0 | BIT8);\r
1150 CopyMem (&((CHAR16 *) Buffer)[1], Password, HDD_PASSWORD_MAX_LENGTH);\r
1151 if ((Identifier & BIT0) != 0) {\r
1152 ((CHAR16 *) Buffer)[17] = MasterPasswordIdentifier;\r
1153 }\r
1154\r
1155 Packet.OutDataBuffer = Buffer;\r
1156 Packet.OutTransferLength = sizeof (Buffer);\r
1157 Packet.Timeout = ATA_TIMEOUT;\r
1158\r
1159 Status = AtaPassThru->PassThru (\r
1160 AtaPassThru,\r
1161 Port,\r
1162 PortMultiplierPort,\r
1163 &Packet,\r
1164 NULL\r
1165 );\r
1166 if (!EFI_ERROR (Status) &&\r
1167 ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&\r
1168 ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {\r
1169 Status = EFI_DEVICE_ERROR;\r
1170 }\r
1171\r
1172 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
1173\r
1174 ZeroMem (Buffer, sizeof (Buffer));\r
1175\r
1176 DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));\r
1177 return Status;\r
1178}\r
1179\r
1180/**\r
1181 Get attached harddisk model number from identify data buffer.\r
1182\r
1183 @param[in] IdentifyData Pointer to identify data buffer.\r
1184 @param[in, out] String The buffer to store harddisk model number.\r
1185\r
1186**/\r
1187VOID\r
1188GetHddDeviceModelNumber (\r
1189 IN ATA_IDENTIFY_DATA *IdentifyData,\r
1190 IN OUT CHAR16 *String\r
1191 )\r
1192{\r
1193 UINTN Index;\r
1194\r
1195 //\r
1196 // Swap the byte order in the original module name.\r
1197 // From Ata spec, the maximum length is 40 bytes.\r
1198 //\r
1199 for (Index = 0; Index < 40; Index += 2) {\r
1200 String[Index] = IdentifyData->ModelName[Index + 1];\r
1201 String[Index + 1] = IdentifyData->ModelName[Index];\r
1202 }\r
1203\r
1204 //\r
1205 // Chap it off after 20 characters\r
1206 //\r
1207 String[20] = L'\0';\r
1208\r
1209 return ;\r
1210}\r
1211\r
1212/**\r
1213 Get password input from the popup windows.\r
1214\r
1215 @param[in] PopUpString1 Pop up string 1.\r
1216 @param[in] PopUpString2 Pop up string 2.\r
1217 @param[in, out] Password The buffer to hold the input password.\r
1218\r
1219 @retval EFI_ABORTED It is given up by pressing 'ESC' key.\r
1220 @retval EFI_SUCCESS Get password input successfully.\r
1221\r
1222**/\r
1223EFI_STATUS\r
1224PopupHddPasswordInputWindows (\r
1225 IN CHAR16 *PopUpString1,\r
1226 IN CHAR16 *PopUpString2,\r
1227 IN OUT CHAR8 *Password\r
1228 )\r
1229{\r
1230 EFI_INPUT_KEY Key;\r
1231 UINTN Length;\r
1232 CHAR16 Mask[HDD_PASSWORD_MAX_LENGTH + 1];\r
1233 CHAR16 Unicode[HDD_PASSWORD_MAX_LENGTH + 1];\r
1234 CHAR8 Ascii[HDD_PASSWORD_MAX_LENGTH + 1];\r
1235\r
1236 ZeroMem (Unicode, sizeof (Unicode));\r
1237 ZeroMem (Ascii, sizeof (Ascii));\r
1238 ZeroMem (Mask, sizeof (Mask));\r
1239\r
1240 gST->ConOut->ClearScreen(gST->ConOut);\r
1241\r
1242 Length = 0;\r
1243 while (TRUE) {\r
1244 Mask[Length] = L'_';\r
1245 if (PopUpString2 == NULL) {\r
1246 CreatePopUp (\r
1247 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1248 &Key,\r
1249 PopUpString1,\r
1250 L"---------------------",\r
1251 Mask,\r
1252 NULL\r
1253 );\r
1254 } else {\r
1255 CreatePopUp (\r
1256 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1257 &Key,\r
1258 PopUpString1,\r
1259 PopUpString2,\r
1260 L"---------------------",\r
1261 Mask,\r
1262 NULL\r
1263 );\r
1264 }\r
1265 //\r
1266 // Check key.\r
1267 //\r
1268 if (Key.ScanCode == SCAN_NULL) {\r
1269 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1270 //\r
1271 // Add the null terminator.\r
1272 //\r
1273 Unicode[Length] = 0;\r
1274 break;\r
1275 } else if ((Key.UnicodeChar == CHAR_NULL) ||\r
1276 (Key.UnicodeChar == CHAR_TAB) ||\r
1277 (Key.UnicodeChar == CHAR_LINEFEED)\r
1278 ) {\r
1279 continue;\r
1280 } else {\r
1281 if (Key.UnicodeChar == CHAR_BACKSPACE) {\r
1282 if (Length > 0) {\r
1283 Unicode[Length] = 0;\r
1284 Mask[Length] = 0;\r
1285 Length--;\r
1286 }\r
1287 } else {\r
1288 Unicode[Length] = Key.UnicodeChar;\r
1289 Mask[Length] = L'*';\r
1290 Length++;\r
1291 if (Length == HDD_PASSWORD_MAX_LENGTH) {\r
1292 //\r
1293 // Add the null terminator.\r
1294 //\r
1295 Unicode[Length] = 0;\r
1296 Mask[Length] = 0;\r
1297 break;\r
1298 }\r
1299 }\r
1300 }\r
1301 }\r
1302\r
1303 if (Key.ScanCode == SCAN_ESC) {\r
1304 ZeroMem (Unicode, sizeof (Unicode));\r
1305 ZeroMem (Ascii, sizeof (Ascii));\r
1306 gST->ConOut->ClearScreen(gST->ConOut);\r
1307 return EFI_ABORTED;\r
1308 }\r
1309 }\r
1310\r
1311 UnicodeStrToAsciiStrS (Unicode, Ascii, sizeof (Ascii));\r
1312 CopyMem (Password, Ascii, HDD_PASSWORD_MAX_LENGTH);\r
1313 ZeroMem (Unicode, sizeof (Unicode));\r
1314 ZeroMem (Ascii, sizeof (Ascii));\r
1315\r
1316 gST->ConOut->ClearScreen(gST->ConOut);\r
1317 return EFI_SUCCESS;\r
1318}\r
1319\r
1320/**\r
1321 Check if disk is locked, show popup window and ask for password if it is.\r
1322\r
1323 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
1324 @param[in] Port The port number of attached ATA device.\r
1325 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
1326 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1327\r
1328**/\r
1329VOID\r
1330HddPasswordRequestPassword (\r
1331 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1332 IN UINT16 Port,\r
1333 IN UINT16 PortMultiplierPort,\r
1334 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1335 )\r
1336{\r
1337 EFI_STATUS Status;\r
1338 CHAR16 PopUpString[100];\r
1339 ATA_IDENTIFY_DATA IdentifyData;\r
1340 EFI_INPUT_KEY Key;\r
1341 UINT16 RetryCount;\r
1342 CHAR8 Password[HDD_PASSWORD_MAX_LENGTH];\r
1343\r
1344 RetryCount = 0;\r
1345\r
1346 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1347\r
1348 UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Unlock: %s", ConfigFormEntry->HddString);\r
1349\r
1350 //\r
1351 // Check the device security status.\r
1352 //\r
1353 if ((ConfigFormEntry->IfrData.SecurityStatus.Supported) &&\r
1354 (ConfigFormEntry->IfrData.SecurityStatus.Enabled)) {\r
1355 //\r
1356 // As soon as the HDD password is in enabled state, we pop up a window to unlock hdd\r
1357 // no matter it's really in locked or unlocked state.\r
1358 // This way forces user to enter password every time to provide best safety.\r
1359 //\r
1360 while (TRUE) {\r
1361 Status = PopupHddPasswordInputWindows (PopUpString, NULL, Password);\r
1362 if (!EFI_ERROR (Status)) {\r
1363 //\r
1364 // The HDD is in locked state, unlock it by user input.\r
1365 //\r
1366 if (!PasswordIsFullZero (Password)) {\r
1367 if (!ConfigFormEntry->IfrData.SecurityStatus.Frozen) {\r
1368 Status = UnlockHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, Password);\r
1369 } else {\r
1370 //\r
1371 // Use saved HDD password variable to validate HDD password\r
1372 // when the device is at frozen state.\r
1373 //\r
1374 Status = ValidateHddPassword (ConfigFormEntry, Password);\r
1375 }\r
1376 } else {\r
1377 Status = EFI_INVALID_PARAMETER;\r
1378 }\r
1379 if (!EFI_ERROR (Status)) {\r
1380 CopyMem (ConfigFormEntry->Password, Password, HDD_PASSWORD_MAX_LENGTH);\r
1381 if (!ConfigFormEntry->IfrData.SecurityStatus.Frozen) {\r
1382 SaveHddPasswordVariable (ConfigFormEntry, Password);\r
1383 }\r
1384 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1385 Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);\r
1386 ASSERT_EFI_ERROR (Status);\r
1387\r
1388 //\r
1389 // Check the device security status again.\r
1390 //\r
1391 GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);\r
1392 return;\r
1393 }\r
1394\r
1395 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1396\r
1397 if (EFI_ERROR (Status)) {\r
1398 RetryCount ++;\r
1399 if (RetryCount < MAX_HDD_PASSWORD_RETRY_COUNT) {\r
1400 do {\r
1401 CreatePopUp (\r
1402 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1403 &Key,\r
1404 L"Invalid password.",\r
1405 L"Press ENTER to retry",\r
1406 NULL\r
1407 );\r
1408 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1409 continue;\r
1410 } else {\r
1411 do {\r
1412 CreatePopUp (\r
1413 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1414 &Key,\r
1415 L"Hdd password retry count is expired. Please shutdown the machine.",\r
1416 L"Press ENTER to shutdown",\r
1417 NULL\r
1418 );\r
1419 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1420 gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
1421 break;\r
1422 }\r
1423 }\r
1424 } else if (Status == EFI_ABORTED) {\r
1425 if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {\r
1426 //\r
1427 // Current device in the lock status and\r
1428 // User not input password and press ESC,\r
1429 // keep device in lock status and continue boot.\r
1430 //\r
1431 do {\r
1432 CreatePopUp (\r
1433 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1434 &Key,\r
1435 L"Press ENTER to skip the request and continue boot,",\r
1436 L"Press ESC to input password again",\r
1437 NULL\r
1438 );\r
1439 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1440\r
1441 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1442 gST->ConOut->ClearScreen(gST->ConOut);\r
1443 //\r
1444 // Keep lock and continue boot.\r
1445 //\r
1446 return;\r
1447 } else {\r
1448 //\r
1449 // Let user input password again.\r
1450 //\r
1451 continue;\r
1452 }\r
1453 } else {\r
1454 //\r
1455 // Current device in the unlock status and\r
1456 // User not input password and press ESC,\r
1457 // Shutdown the device.\r
1458 //\r
1459 do {\r
1460 CreatePopUp (\r
1461 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1462 &Key,\r
1463 L"Press ENTER to shutdown, Press ESC to input password again",\r
1464 NULL\r
1465 );\r
1466 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1467\r
1468 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1469 gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
1470 } else {\r
1471 //\r
1472 // Let user input password again.\r
1473 //\r
1474 continue;\r
1475 }\r
1476 }\r
1477 }\r
1478 }\r
1479 }\r
1480}\r
1481\r
1482/**\r
1483 Process Set User Pwd HDD password request.\r
1484\r
1485 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
1486 @param[in] Port The port number of attached ATA device.\r
1487 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
1488 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1489\r
1490**/\r
1491VOID\r
1492ProcessHddPasswordRequestSetUserPwd (\r
1493 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1494 IN UINT16 Port,\r
1495 IN UINT16 PortMultiplierPort,\r
1496 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1497 )\r
1498{\r
1499 EFI_STATUS Status;\r
1500 CHAR16 PopUpString[100];\r
1501 ATA_IDENTIFY_DATA IdentifyData;\r
1502 EFI_INPUT_KEY Key;\r
1503 UINT16 RetryCount;\r
1504 CHAR8 Password[HDD_PASSWORD_MAX_LENGTH];\r
1505 CHAR8 PasswordConfirm[HDD_PASSWORD_MAX_LENGTH];\r
1506\r
1507 RetryCount = 0;\r
1508\r
1509 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1510\r
1511 if (ConfigFormEntry->IfrData.SecurityStatus.Frozen) {\r
1512 DEBUG ((DEBUG_INFO, "%s is frozen, do nothing\n", ConfigFormEntry->HddString));\r
1513 return;\r
1514 }\r
1515\r
1516 if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {\r
1517 DEBUG ((DEBUG_INFO, "%s is locked, do nothing\n", ConfigFormEntry->HddString));\r
1518 return;\r
1519 }\r
1520\r
1521 UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Set User Pwd: %s", ConfigFormEntry->HddString);\r
1522\r
1523 //\r
1524 // Check the device security status.\r
1525 //\r
1526 if (ConfigFormEntry->IfrData.SecurityStatus.Supported) {\r
1527 while (TRUE) {\r
1528 Status = PopupHddPasswordInputWindows (PopUpString, L"Please type in your new password", Password);\r
1529 if (!EFI_ERROR (Status)) {\r
1530 Status = PopupHddPasswordInputWindows (PopUpString, L"Please confirm your new password", PasswordConfirm);\r
1531 if (!EFI_ERROR (Status)) {\r
1532 if (CompareMem (Password, PasswordConfirm, HDD_PASSWORD_MAX_LENGTH) == 0) {\r
1533 if (!PasswordIsFullZero (Password)) {\r
1534 Status = SetHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, 1, 0, Password);\r
1535 } else {\r
1536 if (ConfigFormEntry->IfrData.SecurityStatus.Enabled) {\r
1537 Status = DisableHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, ConfigFormEntry->Password);\r
1538 } else {\r
1539 Status = EFI_INVALID_PARAMETER;\r
1540 }\r
1541 }\r
1542 if (!EFI_ERROR (Status)) {\r
1543 CopyMem (ConfigFormEntry->Password, Password, HDD_PASSWORD_MAX_LENGTH);\r
1544 SaveHddPasswordVariable (ConfigFormEntry, Password);\r
1545 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1546 ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);\r
1547 Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);\r
1548 ASSERT_EFI_ERROR (Status);\r
1549\r
1550 //\r
1551 // Check the device security status again.\r
1552 //\r
1553 GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);\r
1554 return;\r
1555 } else {\r
1556 do {\r
1557 CreatePopUp (\r
1558 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1559 &Key,\r
1560 L"Set/Disable User Pwd failed or invalid password.",\r
1561 L"Press ENTER to retry",\r
1562 NULL\r
1563 );\r
1564 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1565 }\r
1566 } else {\r
1567 do {\r
1568 CreatePopUp (\r
1569 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1570 &Key,\r
1571 L"Passwords are not the same.",\r
1572 L"Press ENTER to retry",\r
1573 NULL\r
1574 );\r
1575 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1576 Status = EFI_INVALID_PARAMETER;\r
1577 }\r
1578 }\r
1579\r
1580 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1581 ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);\r
1582\r
1583 if (EFI_ERROR (Status)) {\r
1584 RetryCount ++;\r
1585 if (RetryCount >= MAX_HDD_PASSWORD_RETRY_COUNT) {\r
1586 do {\r
1587 CreatePopUp (\r
1588 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1589 &Key,\r
1590 L"Hdd password retry count is expired.",\r
1591 L"Press ENTER to skip the request and continue boot",\r
1592 NULL\r
1593 );\r
1594 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1595 gST->ConOut->ClearScreen(gST->ConOut);\r
1596 return;\r
1597 }\r
1598 }\r
1599 } else if (Status == EFI_ABORTED) {\r
1600 do {\r
1601 CreatePopUp (\r
1602 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1603 &Key,\r
1604 L"Press ENTER to skip the request and continue boot,",\r
1605 L"Press ESC to input password again",\r
1606 NULL\r
1607 );\r
1608 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1609\r
1610 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1611 gST->ConOut->ClearScreen(gST->ConOut);\r
1612 return;\r
1613 } else {\r
1614 //\r
1615 // Let user input password again.\r
1616 //\r
1617 continue;\r
1618 }\r
1619 }\r
1620 }\r
1621 }\r
1622}\r
1623\r
1624/**\r
1625 Process Set Master Pwd HDD password request.\r
1626\r
1627 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
1628 @param[in] Port The port number of attached ATA device.\r
1629 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
1630 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1631\r
1632**/\r
1633VOID\r
1634ProcessHddPasswordRequestSetMasterPwd (\r
1635 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1636 IN UINT16 Port,\r
1637 IN UINT16 PortMultiplierPort,\r
1638 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1639 )\r
1640{\r
1641 EFI_STATUS Status;\r
1642 CHAR16 PopUpString[100];\r
1643 EFI_INPUT_KEY Key;\r
1644 UINT16 RetryCount;\r
1645 CHAR8 Password[HDD_PASSWORD_MAX_LENGTH];\r
1646 CHAR8 PasswordConfirm[HDD_PASSWORD_MAX_LENGTH];\r
1647\r
1648 RetryCount = 0;\r
1649\r
1650 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1651\r
1652 if (ConfigFormEntry->IfrData.SecurityStatus.Frozen) {\r
1653 DEBUG ((DEBUG_INFO, "%s is frozen, do nothing\n", ConfigFormEntry->HddString));\r
1654 return;\r
1655 }\r
1656\r
1657 if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {\r
1658 DEBUG ((DEBUG_INFO, "%s is locked, do nothing\n", ConfigFormEntry->HddString));\r
1659 return;\r
1660 }\r
1661\r
1662 UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Set Master Pwd: %s", ConfigFormEntry->HddString);\r
1663\r
1664 //\r
1665 // Check the device security status.\r
1666 //\r
1667 if (ConfigFormEntry->IfrData.SecurityStatus.Supported) {\r
1668 while (TRUE) {\r
1669 Status = PopupHddPasswordInputWindows (PopUpString, L"Please type in your new password", Password);\r
1670 if (!EFI_ERROR (Status)) {\r
1671 Status = PopupHddPasswordInputWindows (PopUpString, L"Please confirm your new password", PasswordConfirm);\r
1672 if (!EFI_ERROR (Status)) {\r
1673 if (CompareMem (Password, PasswordConfirm, HDD_PASSWORD_MAX_LENGTH) == 0) {\r
1674 if (!PasswordIsFullZero (Password)) {\r
1675 Status = SetHddPassword (AtaPassThru, Port, PortMultiplierPort, 1, 1, 1, Password);\r
1676 } else {\r
1677 Status = EFI_INVALID_PARAMETER;\r
1678 }\r
1679 if (!EFI_ERROR (Status)) {\r
1680 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1681 ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);\r
1682 return;\r
1683 } else {\r
1684 do {\r
1685 CreatePopUp (\r
1686 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1687 &Key,\r
1688 L"Set Master Pwd failed or invalid password.",\r
1689 L"Press ENTER to retry",\r
1690 NULL\r
1691 );\r
1692 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1693 }\r
1694 } else {\r
1695 do {\r
1696 CreatePopUp (\r
1697 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1698 &Key,\r
1699 L"Passwords are not the same.",\r
1700 L"Press ENTER to retry",\r
1701 NULL\r
1702 );\r
1703 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1704 Status = EFI_INVALID_PARAMETER;\r
1705 }\r
1706 }\r
1707\r
1708 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1709 ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);\r
1710\r
1711 if (EFI_ERROR (Status)) {\r
1712 RetryCount ++;\r
1713 if (RetryCount >= MAX_HDD_PASSWORD_RETRY_COUNT) {\r
1714 do {\r
1715 CreatePopUp (\r
1716 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1717 &Key,\r
1718 L"Hdd password retry count is expired.",\r
1719 L"Press ENTER to skip the request and continue boot",\r
1720 NULL\r
1721 );\r
1722 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1723 gST->ConOut->ClearScreen(gST->ConOut);\r
1724 return;\r
1725 }\r
1726 }\r
1727 } else if (Status == EFI_ABORTED) {\r
1728 do {\r
1729 CreatePopUp (\r
1730 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1731 &Key,\r
1732 L"Press ENTER to skip the request and continue boot,",\r
1733 L"Press ESC to input password again",\r
1734 NULL\r
1735 );\r
1736 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1737\r
1738 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1739 gST->ConOut->ClearScreen(gST->ConOut);\r
1740 return;\r
1741 } else {\r
1742 //\r
1743 // Let user input password again.\r
1744 //\r
1745 continue;\r
1746 }\r
1747 }\r
1748 }\r
1749 }\r
1750}\r
1751\r
1752/**\r
1753 Process HDD password request.\r
1754\r
1755 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
1756 @param[in] Port The port number of attached ATA device.\r
1757 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
1758 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1759\r
1760**/\r
1761VOID\r
1762ProcessHddPasswordRequest (\r
1763 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1764 IN UINT16 Port,\r
1765 IN UINT16 PortMultiplierPort,\r
1766 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1767 )\r
1768{\r
1769 EFI_STATUS Status;\r
1770 HDD_PASSWORD_REQUEST_VARIABLE *TempVariable;\r
1771 HDD_PASSWORD_REQUEST_VARIABLE *Variable;\r
1772 UINTN VariableSize;\r
1773\r
1774 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
1775\r
1776 if (mHddPasswordRequestVariable == NULL) {\r
1777 Status = GetVariable2 (\r
1778 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1779 &mHddPasswordVendorGuid,\r
1780 (VOID **) &Variable,\r
1781 &VariableSize\r
1782 );\r
1783 if (EFI_ERROR (Status) || (Variable == NULL)) {\r
1784 return;\r
1785 }\r
1786 mHddPasswordRequestVariable = Variable;\r
1787 mHddPasswordRequestVariableSize = VariableSize;\r
1788\r
1789 //\r
1790 // Delete the HDD password request variable.\r
1791 //\r
1792 Status = gRT->SetVariable (\r
1793 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1794 &mHddPasswordVendorGuid,\r
1795 0,\r
1796 0,\r
1797 NULL\r
1798 );\r
1799 ASSERT_EFI_ERROR (Status);\r
1800 } else {\r
1801 Variable = mHddPasswordRequestVariable;\r
1802 VariableSize = mHddPasswordRequestVariableSize;\r
1803 }\r
1804\r
1805 //\r
1806 // Process the HDD password requests.\r
1807 //\r
1808 TempVariable = Variable;\r
1809 while (VariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {\r
1810 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
1811 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
1812 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
1813 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
1814 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
1815 //\r
1816 // Found the node for the HDD password device.\r
1817 //\r
1818 if (TempVariable->Request.UserPassword != 0) {\r
1819 ProcessHddPasswordRequestSetUserPwd (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);\r
1820 }\r
1821 if (TempVariable->Request.MasterPassword != 0) {\r
1822 ProcessHddPasswordRequestSetMasterPwd (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);\r
1823 }\r
1824\r
1825 break;\r
1826 }\r
1827\r
1828 VariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1829 TempVariable += 1;\r
1830 }\r
1831\r
1832 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
1833}\r
1834\r
1835/**\r
1836 Get saved HDD password request.\r
1837\r
1838 @param[in, out] ConfigFormEntry The HDD Password configuration form entry.\r
1839\r
1840**/\r
1841VOID\r
1842GetSavedHddPasswordRequest (\r
1843 IN OUT HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1844 )\r
1845{\r
1846 EFI_STATUS Status;\r
1847 HDD_PASSWORD_REQUEST_VARIABLE *TempVariable;\r
1848 HDD_PASSWORD_REQUEST_VARIABLE *Variable;\r
1849 UINTN VariableSize;\r
1850\r
1851 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
1852\r
1853 Variable = NULL;\r
1854 VariableSize = 0;\r
1855\r
1856 Status = GetVariable2 (\r
1857 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1858 &mHddPasswordVendorGuid,\r
1859 (VOID **) &Variable,\r
1860 &VariableSize\r
1861 );\r
1862 if (EFI_ERROR (Status) || (Variable == NULL)) {\r
1863 return;\r
1864 }\r
1865\r
1866 TempVariable = Variable;\r
1867 while (VariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {\r
1868 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
1869 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
1870 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
1871 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
1872 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
1873 //\r
1874 // Found the node for the HDD password device.\r
1875 // Get the HDD password request.\r
1876 //\r
1877 CopyMem (&ConfigFormEntry->IfrData.Request, &TempVariable->Request, sizeof (HDD_PASSWORD_REQUEST));\r
1878 DEBUG ((\r
1879 DEBUG_INFO,\r
1880 "HddPasswordRequest got: 0x%x\n",\r
1881 ConfigFormEntry->IfrData.Request\r
1882 ));\r
1883 break;\r
1884 }\r
1885 VariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1886 TempVariable += 1;\r
1887 }\r
1888\r
1889 FreePool (Variable);\r
1890\r
1891 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
1892}\r
1893\r
1894/**\r
1895 Save HDD password request.\r
1896\r
1897 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1898\r
1899**/\r
1900VOID\r
1901SaveHddPasswordRequest (\r
1902 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1903 )\r
1904{\r
1905 EFI_STATUS Status;\r
1906 HDD_PASSWORD_REQUEST_VARIABLE *TempVariable;\r
1907 UINTN TempVariableSize;\r
1908 HDD_PASSWORD_REQUEST_VARIABLE *Variable;\r
1909 UINTN VariableSize;\r
1910 HDD_PASSWORD_REQUEST_VARIABLE *NewVariable;\r
1911 UINTN NewVariableSize;\r
1912\r
1913 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
1914\r
1915 DEBUG ((\r
1916 DEBUG_INFO,\r
1917 "HddPasswordRequest to save: 0x%x\n",\r
1918 ConfigFormEntry->IfrData.Request\r
1919 ));\r
1920\r
1921 Variable = NULL;\r
1922 VariableSize = 0;\r
1923 NewVariable = NULL;\r
1924 NewVariableSize = 0;\r
1925\r
1926 Status = GetVariable2 (\r
1927 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1928 &mHddPasswordVendorGuid,\r
1929 (VOID **) &Variable,\r
1930 &VariableSize\r
1931 );\r
1932 if (!EFI_ERROR (Status) && (Variable != NULL)) {\r
1933 TempVariable = Variable;\r
1934 TempVariableSize = VariableSize;\r
1935 while (TempVariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {\r
1936 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
1937 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
1938 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
1939 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
1940 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
1941 //\r
1942 // Found the node for the HDD password device.\r
1943 // Update the HDD password request.\r
1944 //\r
1945 CopyMem (&TempVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));\r
1946 NewVariable = Variable;\r
1947 NewVariableSize = VariableSize;\r
1948 break;\r
1949 }\r
1950 TempVariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1951 TempVariable += 1;\r
1952 }\r
1953 if (NewVariable == NULL) {\r
1954 //\r
1955 // The node for the HDD password device is not found.\r
1956 // Create node for the HDD password device.\r
1957 //\r
1958 NewVariableSize = VariableSize + sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1959 NewVariable = AllocateZeroPool (NewVariableSize);\r
1960 ASSERT (NewVariable != NULL);\r
1961 CopyMem (NewVariable, Variable, VariableSize);\r
1962 TempVariable = (HDD_PASSWORD_REQUEST_VARIABLE *) ((UINTN) NewVariable + VariableSize);\r
1963 TempVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
1964 TempVariable->Device.Device = (UINT8) ConfigFormEntry->Device;\r
1965 TempVariable->Device.Function = (UINT8) ConfigFormEntry->Function;\r
1966 TempVariable->Device.Port = ConfigFormEntry->Port;\r
1967 TempVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
1968 CopyMem (&TempVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));\r
1969 }\r
1970 } else {\r
1971 NewVariableSize = sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1972 NewVariable = AllocateZeroPool (NewVariableSize);\r
1973 ASSERT (NewVariable != NULL);\r
1974 NewVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
1975 NewVariable->Device.Device = (UINT8) ConfigFormEntry->Device;\r
1976 NewVariable->Device.Function = (UINT8) ConfigFormEntry->Function;\r
1977 NewVariable->Device.Port = ConfigFormEntry->Port;\r
1978 NewVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
1979 CopyMem (&NewVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));\r
1980 }\r
1981 Status = gRT->SetVariable (\r
1982 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1983 &mHddPasswordVendorGuid,\r
1984 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
1985 NewVariableSize,\r
1986 NewVariable\r
1987 );\r
1988 if (EFI_ERROR (Status)) {\r
1989 DEBUG ((DEBUG_INFO, "HddPasswordRequest variable set failed (%r)\n", Status));\r
1990 }\r
1991 if (NewVariable != Variable) {\r
1992 FreePool (NewVariable);\r
1993 }\r
1994 if (Variable != NULL) {\r
1995 FreePool (Variable);\r
1996 }\r
1997\r
1998 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
1999}\r
2000\r
2001/**\r
2002 Get the HDD Password configuration form entry by the index of the goto opcode actived.\r
2003\r
2004 @param[in] Index The 0-based index of the goto opcode actived.\r
2005\r
2006 @return The HDD Password configuration form entry found.\r
2007**/\r
2008HDD_PASSWORD_CONFIG_FORM_ENTRY *\r
2009HddPasswordGetConfigFormEntryByIndex (\r
2010 IN UINT32 Index\r
2011 )\r
2012{\r
2013 LIST_ENTRY *Entry;\r
2014 UINT32 CurrentIndex;\r
2015 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
2016\r
2017 CurrentIndex = 0;\r
2018 ConfigFormEntry = NULL;\r
2019\r
2020 EFI_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
2021 if (CurrentIndex == Index) {\r
2022 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
2023 break;\r
2024 }\r
2025\r
2026 CurrentIndex++;\r
2027 }\r
2028\r
2029 return ConfigFormEntry;\r
2030}\r
2031\r
2032/**\r
2033 This function allows the caller to request the current\r
2034 configuration for one or more named elements. The resulting\r
2035 string is in <ConfigAltResp> format. Any and all alternative\r
2036 configuration strings shall also be appended to the end of the\r
2037 current configuration string. If they are, they must appear\r
2038 after the current configuration. They must contain the same\r
2039 routing (GUID, NAME, PATH) as the current configuration string.\r
2040 They must have an additional description indicating the type of\r
2041 alternative configuration the string represents,\r
2042 "ALTCFG=<StringToken>". That <StringToken> (when\r
2043 converted from Hex UNICODE to binary) is a reference to a\r
2044 string in the associated string pack.\r
2045\r
2046 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2047 @param[in] Request A null-terminated Unicode string in\r
2048 <ConfigRequest> format. Note that this\r
2049 includes the routing information as well as\r
2050 the configurable name / value pairs. It is\r
2051 invalid for this string to be in\r
2052 <MultiConfigRequest> format.\r
2053 @param[out] Progress On return, points to a character in the\r
2054 Request string. Points to the string's null\r
2055 terminator if request was successful. Points\r
2056 to the most recent "&" before the first\r
2057 failing name / value pair (or the beginning\r
2058 of the string if the failure is in the first\r
2059 name / value pair) if the request was not\r
2060 successful.\r
2061 @param[out] Results A null-terminated Unicode string in\r
2062 <ConfigAltResp> format which has all values\r
2063 filled in for the names in the Request string.\r
2064 String to be allocated by the called function.\r
2065\r
2066 @retval EFI_SUCCESS The Results string is filled with the\r
2067 values corresponding to all requested\r
2068 names.\r
2069 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
2070 parts of the results that must be\r
2071 stored awaiting possible future\r
2072 protocols.\r
2073 @retval EFI_INVALID_PARAMETER For example, passing in a NULL\r
2074 for the Request parameter\r
2075 would result in this type of\r
2076 error. In this case, the\r
2077 Progress parameter would be\r
2078 set to NULL.\r
2079 @retval EFI_NOT_FOUND Routing data doesn't match any\r
2080 known driver. Progress set to the\r
2081 first character in the routing header.\r
2082 Note: There is no requirement that the\r
2083 driver validate the routing data. It\r
2084 must skip the <ConfigHdr> in order to\r
2085 process the names.\r
2086 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
2087 to most recent & before the\r
2088 error or the beginning of the\r
2089 string.\r
2090 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
2091 to the & before the name in\r
2092 question.Currently not implemented.\r
2093**/\r
2094EFI_STATUS\r
2095EFIAPI\r
2096HddPasswordFormExtractConfig (\r
2097 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2098 IN CONST EFI_STRING Request,\r
2099 OUT EFI_STRING *Progress,\r
2100 OUT EFI_STRING *Results\r
2101 )\r
2102{\r
2103 EFI_STATUS Status;\r
2104 UINTN BufferSize;\r
2105 HDD_PASSWORD_CONFIG *IfrData;\r
2106 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
2107 EFI_STRING ConfigRequestHdr;\r
2108 EFI_STRING ConfigRequest;\r
2109 BOOLEAN AllocatedRequest;\r
2110 UINTN Size;\r
2111\r
2112 if (Progress == NULL || Results == NULL) {\r
2113 return EFI_INVALID_PARAMETER;\r
2114 }\r
2115\r
2116 *Progress = Request;\r
2117 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mHddPasswordVendorGuid, mHddPasswordVendorStorageName)) {\r
2118 return EFI_NOT_FOUND;\r
2119 }\r
2120\r
2121 ConfigRequestHdr = NULL;\r
2122 ConfigRequest = NULL;\r
2123 AllocatedRequest = FALSE;\r
2124 Size = 0;\r
2125\r
2126 Private = HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This);\r
2127 IfrData = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG));\r
2128 ASSERT (IfrData != NULL);\r
2129 if (Private->Current != NULL) {\r
2130 CopyMem (IfrData, &Private->Current->IfrData, sizeof (HDD_PASSWORD_CONFIG));\r
2131 }\r
2132\r
2133 //\r
2134 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
2135 //\r
2136 BufferSize = sizeof (HDD_PASSWORD_CONFIG);\r
2137 ConfigRequest = Request;\r
2138 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
2139 //\r
2140 // Request has no request element, construct full request string.\r
2141 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
2142 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
2143 //\r
2144 ConfigRequestHdr = HiiConstructConfigHdr (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, Private->DriverHandle);\r
2145 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
2146 ConfigRequest = AllocateZeroPool (Size);\r
2147 ASSERT (ConfigRequest != NULL);\r
2148 AllocatedRequest = TRUE;\r
2149 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
2150 FreePool (ConfigRequestHdr);\r
2151 }\r
2152 Status = gHiiConfigRouting->BlockToConfig (\r
2153 gHiiConfigRouting,\r
2154 ConfigRequest,\r
2155 (UINT8 *) IfrData,\r
2156 BufferSize,\r
2157 Results,\r
2158 Progress\r
2159 );\r
2160 FreePool (IfrData);\r
2161 //\r
2162 // Free the allocated config request string.\r
2163 //\r
2164 if (AllocatedRequest) {\r
2165 FreePool (ConfigRequest);\r
2166 ConfigRequest = NULL;\r
2167 }\r
2168\r
2169 //\r
2170 // Set Progress string to the original request string.\r
2171 //\r
2172 if (Request == NULL) {\r
2173 *Progress = NULL;\r
2174 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
2175 *Progress = Request + StrLen (Request);\r
2176 }\r
2177\r
2178 return Status;\r
2179}\r
2180\r
2181/**\r
2182 This function applies changes in a driver's configuration.\r
2183 Input is a Configuration, which has the routing data for this\r
2184 driver followed by name / value configuration pairs. The driver\r
2185 must apply those pairs to its configurable storage. If the\r
2186 driver's configuration is stored in a linear block of data\r
2187 and the driver's name / value pairs are in <BlockConfig>\r
2188 format, it may use the ConfigToBlock helper function (above) to\r
2189 simplify the job. Currently not implemented.\r
2190\r
2191 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2192 @param[in] Configuration A null-terminated Unicode string in\r
2193 <ConfigString> format.\r
2194 @param[out] Progress A pointer to a string filled in with the\r
2195 offset of the most recent '&' before the\r
2196 first failing name / value pair (or the\r
2197 beginn ing of the string if the failure\r
2198 is in the first name / value pair) or\r
2199 the terminating NULL if all was\r
2200 successful.\r
2201\r
2202 @retval EFI_SUCCESS The results have been distributed or are\r
2203 awaiting distribution.\r
2204 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
2205 parts of the results that must be\r
2206 stored awaiting possible future\r
2207 protocols.\r
2208 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
2209 Results parameter would result\r
2210 in this type of error.\r
2211 @retval EFI_NOT_FOUND Target for the specified routing data\r
2212 was not found.\r
2213**/\r
2214EFI_STATUS\r
2215EFIAPI\r
2216HddPasswordFormRouteConfig (\r
2217 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2218 IN CONST EFI_STRING Configuration,\r
2219 OUT EFI_STRING *Progress\r
2220 )\r
2221{\r
2222 if (Configuration == NULL || Progress == NULL) {\r
2223 return EFI_INVALID_PARAMETER;\r
2224 }\r
2225\r
2226 //\r
2227 // Check routing data in <ConfigHdr>.\r
2228 // Note: if only one Storage is used, then this checking could be skipped.\r
2229 //\r
2230 if (!HiiIsConfigHdrMatch (Configuration, &mHddPasswordVendorGuid, mHddPasswordVendorStorageName)) {\r
2231 *Progress = Configuration;\r
2232 return EFI_NOT_FOUND;\r
2233 }\r
2234\r
2235 *Progress = Configuration + StrLen (Configuration);\r
2236 return EFI_SUCCESS;\r
2237}\r
2238\r
2239/**\r
2240 This function is called to provide results data to the driver.\r
2241 This data consists of a unique key that is used to identify\r
2242 which data is either being passed back or being asked for.\r
2243\r
2244 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2245 @param[in] Action Specifies the type of action taken by the browser.\r
2246 @param[in] QuestionId A unique value which is sent to the original\r
2247 exporting driver so that it can identify the type\r
2248 of data to expect. The format of the data tends to\r
2249 vary based on the opcode that enerated the callback.\r
2250 @param[in] Type The type of value for the question.\r
2251 @param[in] Value A pointer to the data being sent to the original\r
2252 exporting driver.\r
2253 @param[out] ActionRequest On return, points to the action requested by the\r
2254 callback function.\r
2255\r
2256 @retval EFI_SUCCESS The callback successfully handled the action.\r
2257 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
2258 variable and its data.\r
2259 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
2260 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
2261 callback.Currently not implemented.\r
2262 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.\r
2263 @retval Others Other errors as indicated.\r
2264**/\r
2265EFI_STATUS\r
2266EFIAPI\r
2267HddPasswordFormCallback (\r
2268 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2269 IN EFI_BROWSER_ACTION Action,\r
2270 IN EFI_QUESTION_ID QuestionId,\r
2271 IN UINT8 Type,\r
2272 IN EFI_IFR_TYPE_VALUE *Value,\r
2273 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
2274 )\r
2275{\r
2276 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
2277 EFI_STRING_ID DeviceFormTitleToken;\r
2278 HDD_PASSWORD_CONFIG *IfrData;\r
2279 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
2280\r
2281 if (ActionRequest != NULL) {\r
2282 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2283 } else {\r
2284 return EFI_INVALID_PARAMETER;\r
2285 }\r
2286\r
2287 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {\r
2288 //\r
2289 // Do nothing for other UEFI Action. Only do call back when data is changing or changed.\r
2290 //\r
2291 return EFI_UNSUPPORTED;\r
2292 }\r
2293\r
2294 Private = HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This);\r
2295\r
2296 //\r
2297 // Retrive data from Browser\r
2298 //\r
2299 IfrData = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG));\r
2300 ASSERT (IfrData != NULL);\r
2301 if (!HiiGetBrowserData (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, sizeof (HDD_PASSWORD_CONFIG), (UINT8 *) IfrData)) {\r
2302 FreePool (IfrData);\r
2303 return EFI_NOT_FOUND;\r
2304 }\r
2305\r
2306 switch (QuestionId) {\r
2307 case KEY_HDD_USER_PASSWORD:\r
2308 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
2309 DEBUG ((DEBUG_INFO, "KEY_HDD_USER_PASSWORD\n"));\r
2310 ConfigFormEntry = Private->Current;\r
2311 ConfigFormEntry->IfrData.Request.UserPassword = Value->b;\r
2312 SaveHddPasswordRequest (ConfigFormEntry);\r
2313 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2314 }\r
2315 break;\r
2316 case KEY_HDD_MASTER_PASSWORD:\r
2317 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
2318 DEBUG ((DEBUG_INFO, "KEY_HDD_MASTER_PASSWORD\n"));\r
2319 ConfigFormEntry = Private->Current;\r
2320 ConfigFormEntry->IfrData.Request.MasterPassword = Value->b;\r
2321 SaveHddPasswordRequest (ConfigFormEntry);\r
2322 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2323 }\r
2324 break;\r
2325\r
2326 default:\r
2327 if ((QuestionId >= KEY_HDD_DEVICE_ENTRY_BASE) && (QuestionId < (mNumberOfHddDevices + KEY_HDD_DEVICE_ENTRY_BASE))) {\r
2328 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
2329 //\r
2330 // In case goto the device configuration form, update the device form title.\r
2331 //\r
2332 ConfigFormEntry = HddPasswordGetConfigFormEntryByIndex ((UINT32) (QuestionId - KEY_HDD_DEVICE_ENTRY_BASE));\r
2333 ASSERT (ConfigFormEntry != NULL);\r
2334\r
2335 DeviceFormTitleToken = (EFI_STRING_ID) STR_HDD_SECURITY_HD;\r
2336 HiiSetString (Private->HiiHandle, DeviceFormTitleToken, ConfigFormEntry->HddString, NULL);\r
2337\r
2338 Private->Current = ConfigFormEntry;\r
2339 CopyMem (IfrData, &ConfigFormEntry->IfrData, sizeof (HDD_PASSWORD_CONFIG));\r
2340 }\r
2341 }\r
2342\r
2343 break;\r
2344 }\r
2345\r
2346 //\r
2347 // Pass changed uncommitted data back to Form Browser\r
2348 //\r
2349 HiiSetBrowserData (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, sizeof (HDD_PASSWORD_CONFIG), (UINT8 *) IfrData, NULL);\r
2350\r
2351 FreePool (IfrData);\r
2352 return EFI_SUCCESS;\r
2353}\r
2354\r
2355/**\r
2356 Updates the HDD Password configuration form to add an entry for the attached\r
2357 ata harddisk device specified by the Controller.\r
2358\r
2359 @param[in] HiiHandle The HII Handle associated with the registered package list.\r
2360 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
2361 @param[in] PciIo Pointer to PCI_IO instance.\r
2362 @param[in] Controller The controller handle of the attached ata controller.\r
2363 @param[in] Bus The bus number of ATA controller.\r
2364 @param[in] Device The device number of ATA controller.\r
2365 @param[in] Function The function number of ATA controller.\r
2366 @param[in] Port The port number of attached ATA device.\r
2367 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
2368\r
2369 @retval EFI_SUCCESS The Hdd Password configuration form is updated.\r
2370 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
2371 @retval Others Other errors as indicated.\r
2372\r
2373**/\r
2374EFI_STATUS\r
2375HddPasswordConfigUpdateForm (\r
2376 IN EFI_HII_HANDLE HiiHandle,\r
2377 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
2378 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2379 IN EFI_HANDLE Controller,\r
2380 IN UINTN Bus,\r
2381 IN UINTN Device,\r
2382 IN UINTN Function,\r
2383 IN UINT16 Port,\r
2384 IN UINT16 PortMultiplierPort\r
2385 )\r
2386{\r
2387 LIST_ENTRY *Entry;\r
2388 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
2389 BOOLEAN EntryExisted;\r
2390 EFI_STATUS Status;\r
2391 VOID *StartOpCodeHandle;\r
2392 VOID *EndOpCodeHandle;\r
2393 EFI_IFR_GUID_LABEL *StartLabel;\r
2394 EFI_IFR_GUID_LABEL *EndLabel;\r
2395 CHAR16 HddString[40];\r
2396 ATA_IDENTIFY_DATA IdentifyData;\r
2397 EFI_DEVICE_PATH_PROTOCOL *AtaDeviceNode;\r
2398\r
2399 ConfigFormEntry = NULL;\r
2400 EntryExisted = FALSE;\r
2401\r
2402 EFI_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
2403 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
2404\r
2405 if ((ConfigFormEntry->Bus == Bus) &&\r
2406 (ConfigFormEntry->Device == Device) &&\r
2407 (ConfigFormEntry->Function == Function) &&\r
2408 (ConfigFormEntry->Port == Port) &&\r
2409 (ConfigFormEntry->PortMultiplierPort == PortMultiplierPort)) {\r
2410 EntryExisted = TRUE;\r
2411 break;\r
2412 }\r
2413 }\r
2414\r
2415 if (!EntryExisted) {\r
2416 //\r
2417 // Add a new form.\r
2418 //\r
2419 ConfigFormEntry = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG_FORM_ENTRY));\r
2420 if (ConfigFormEntry == NULL) {\r
2421 return EFI_OUT_OF_RESOURCES;\r
2422 }\r
2423\r
2424 InitializeListHead (&ConfigFormEntry->Link);\r
2425 ConfigFormEntry->Controller = Controller;\r
2426 ConfigFormEntry->Bus = Bus;\r
2427 ConfigFormEntry->Device = Device;\r
2428 ConfigFormEntry->Function = Function;\r
2429 ConfigFormEntry->Port = Port;\r
2430 ConfigFormEntry->PortMultiplierPort = PortMultiplierPort;\r
2431 ConfigFormEntry->AtaPassThru = AtaPassThru;\r
2432\r
2433 DEBUG ((DEBUG_INFO, "HddPasswordDxe: Create new form for device[%d][%d] at Bus 0x%x Dev 0x%x Func 0x%x\n", Port, PortMultiplierPort, Bus, Device, Function));\r
2434\r
2435 //\r
2436 // Construct the device path for the HDD password device\r
2437 //\r
2438 Status = AtaPassThru->BuildDevicePath (\r
2439 AtaPassThru,\r
2440 Port,\r
2441 PortMultiplierPort,\r
2442 &AtaDeviceNode\r
2443 );\r
2444 if (EFI_ERROR (Status)) {\r
2445 return Status;\r
2446 }\r
2447 ConfigFormEntry->DevicePath = AppendDevicePathNode (DevicePathFromHandle (Controller), AtaDeviceNode);\r
2448 FreePool (AtaDeviceNode);\r
2449 if (ConfigFormEntry->DevicePath == NULL) {\r
2450 return EFI_OUT_OF_RESOURCES;\r
2451 }\r
2452\r
2453 //\r
2454 // Get attached harddisk model number\r
2455 //\r
2456 Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);\r
2457 ASSERT_EFI_ERROR (Status);\r
2458 if (EFI_ERROR (Status)) {\r
2459 return Status;\r
2460 }\r
2461 GetHddDeviceModelNumber (&IdentifyData, HddString);\r
2462 //\r
2463 // Compose the HDD title string and help string of this port and create a new EFI_STRING_ID.\r
2464 //\r
2465 UnicodeSPrint (ConfigFormEntry->HddString, sizeof (ConfigFormEntry->HddString), L"HDD %d:%s", mNumberOfHddDevices, HddString);\r
2466 ConfigFormEntry->TitleToken = HiiSetString (HiiHandle, 0, ConfigFormEntry->HddString, NULL);\r
2467 ConfigFormEntry->TitleHelpToken = HiiSetString (HiiHandle, 0, L"Request to set HDD Password", NULL);\r
2468\r
2469 GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);\r
2470\r
2471 InsertTailList (&mHddPasswordConfigFormList, &ConfigFormEntry->Link);\r
2472\r
2473 //\r
2474 // Init OpCode Handle\r
2475 //\r
2476 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2477 ASSERT (StartOpCodeHandle != NULL);\r
2478\r
2479 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2480 ASSERT (EndOpCodeHandle != NULL);\r
2481\r
2482 //\r
2483 // Create Hii Extend Label OpCode as the start opcode\r
2484 //\r
2485 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
2486 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2487 StartLabel->Number = HDD_DEVICE_ENTRY_LABEL;\r
2488\r
2489 //\r
2490 // Create Hii Extend Label OpCode as the end opcode\r
2491 //\r
2492 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
2493 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2494 EndLabel->Number = HDD_DEVICE_LABEL_END;\r
2495\r
2496 mNumberOfHddDevices = 0;\r
2497 EFI_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
2498 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
2499\r
2500 HiiCreateGotoOpCode (\r
2501 StartOpCodeHandle, // Container for dynamic created opcodes\r
2502 FORMID_HDD_DEVICE_FORM, // Target Form ID\r
2503 ConfigFormEntry->TitleToken, // Prompt text\r
2504 ConfigFormEntry->TitleHelpToken, // Help text\r
2505 EFI_IFR_FLAG_CALLBACK, // Question flag\r
2506 (UINT16) (KEY_HDD_DEVICE_ENTRY_BASE + mNumberOfHddDevices) // Question ID\r
2507 );\r
2508\r
2509 mNumberOfHddDevices++;\r
2510 }\r
2511\r
2512 HiiUpdateForm (\r
2513 HiiHandle,\r
2514 &mHddPasswordVendorGuid,\r
2515 FORMID_HDD_MAIN_FORM,\r
2516 StartOpCodeHandle,\r
2517 EndOpCodeHandle\r
2518 );\r
2519\r
2520 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2521 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2522\r
2523 //\r
2524 // Check if device is locked and prompt for password.\r
2525 //\r
2526 HddPasswordRequestPassword (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);\r
2527\r
2528 //\r
2529 // Process HDD password request from last boot.\r
2530 //\r
2531 ProcessHddPasswordRequest (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);\r
2532 }\r
2533\r
2534 return EFI_SUCCESS;\r
2535}\r
2536\r
2537/**\r
2538 Ata Pass Thru Protocol notification event handler.\r
2539\r
2540 Check attached harddisk status to see if it's locked. If yes, then pop up a password windows to require user input.\r
2541 It also registers a form for user configuration on Hdd password configuration.\r
2542\r
2543 @param[in] Event Event whose notification function is being invoked.\r
2544 @param[in] Context Pointer to the notification function's context.\r
2545\r
2546**/\r
2547VOID\r
2548EFIAPI\r
2549HddPasswordNotificationEvent (\r
2550 IN EFI_EVENT Event,\r
2551 IN VOID *Context\r
2552 )\r
2553{\r
2554 EFI_STATUS Status;\r
2555 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
2556 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
2557 UINT16 Port;\r
2558 UINT16 PortMultiplierPort;\r
2559 EFI_HANDLE Controller;\r
2560 EFI_HANDLE *HandleBuffer;\r
2561 UINTN HandleCount;\r
2562 UINTN Index;\r
2563 EFI_PCI_IO_PROTOCOL *PciIo;\r
2564 UINTN SegNum;\r
2565 UINTN BusNum;\r
2566 UINTN DevNum;\r
2567 UINTN FuncNum;\r
2568\r
2569 if (mHddPasswordEndOfDxe) {\r
2570 gBS->CloseEvent (Event);\r
2571 return;\r
2572 }\r
2573\r
2574 Private = (HDD_PASSWORD_DXE_PRIVATE_DATA *)Context;\r
2575\r
2576 //\r
2577 // Locate all handles of AtaPassThru protocol\r
2578 //\r
2579 Status = gBS->LocateHandleBuffer (\r
2580 ByProtocol,\r
2581 &gEfiAtaPassThruProtocolGuid,\r
2582 NULL,\r
2583 &HandleCount,\r
2584 &HandleBuffer\r
2585 );\r
2586 if (EFI_ERROR (Status)) {\r
2587 return ;\r
2588 }\r
2589\r
2590 //\r
2591 // Check attached hard disk status to see if it's locked\r
2592 //\r
2593 for (Index = 0; Index < HandleCount; Index += 1) {\r
2594 Controller = HandleBuffer[Index];\r
2595 Status = gBS->HandleProtocol (\r
2596 Controller,\r
2597 &gEfiAtaPassThruProtocolGuid,\r
2598 (VOID **) &AtaPassThru\r
2599 );\r
2600 if (EFI_ERROR (Status)) {\r
2601 break;\r
2602 }\r
2603\r
2604 //\r
2605 // Ignore those logical ATA_PASS_THRU instance.\r
2606 //\r
2607 if ((AtaPassThru->Mode->Attributes & EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL) == 0) {\r
2608 continue;\r
2609 }\r
2610\r
2611 Status = gBS->HandleProtocol (\r
2612 Controller,\r
2613 &gEfiPciIoProtocolGuid,\r
2614 (VOID **) &PciIo\r
2615 );\r
2616 ASSERT_EFI_ERROR (Status);\r
2617 if (EFI_ERROR (Status)) {\r
2618 break;\r
2619 }\r
2620\r
2621 Status = PciIo->GetLocation (\r
2622 PciIo,\r
2623 &SegNum,\r
2624 &BusNum,\r
2625 &DevNum,\r
2626 &FuncNum\r
2627 );\r
2628 ASSERT_EFI_ERROR (Status);\r
2629 if (EFI_ERROR (Status)) {\r
2630 break;\r
2631 }\r
2632\r
2633 //\r
2634 // Assume and only support Segment == 0.\r
2635 //\r
2636 ASSERT (SegNum == 0);\r
2637\r
2638 //\r
2639 // traverse all attached harddisk devices to update form and unlock it\r
2640 //\r
2641 Port = 0xFFFF;\r
2642\r
2643 while (TRUE) {\r
2644 Status = AtaPassThru->GetNextPort (AtaPassThru, &Port);\r
2645 if (EFI_ERROR (Status)) {\r
2646 //\r
2647 // We cannot find more legal port then we are done.\r
2648 //\r
2649 break;\r
2650 }\r
2651\r
2652 PortMultiplierPort = 0xFFFF;\r
2653 while (TRUE) {\r
2654 Status = AtaPassThru->GetNextDevice (AtaPassThru, Port, &PortMultiplierPort);\r
2655 if (EFI_ERROR (Status)) {\r
2656 //\r
2657 // We cannot find more legal port multiplier port number for ATA device\r
2658 // on the port, then we are done.\r
2659 //\r
2660 break;\r
2661 }\r
2662 //\r
2663 // Find out the attached harddisk devices.\r
2664 // Try to add a HDD Password configuration page for the attached devices.\r
2665 //\r
2666 gBS->RestoreTPL (TPL_APPLICATION);\r
2667 Status = HddPasswordConfigUpdateForm (Private->HiiHandle, AtaPassThru, PciIo, Controller, BusNum, DevNum, FuncNum, Port, PortMultiplierPort);\r
2668 gBS->RaiseTPL (TPL_CALLBACK);\r
2669 if (EFI_ERROR (Status)) {\r
2670 break;\r
2671 }\r
2672 }\r
2673 }\r
2674 }\r
2675\r
2676 FreePool (HandleBuffer);\r
2677 return ;\r
2678}\r
2679\r
2680/**\r
2681 Initialize the HDD Password configuration form.\r
2682\r
2683 @param[out] Instance Pointer to private instance.\r
2684\r
2685 @retval EFI_SUCCESS The HDD Password configuration form is initialized.\r
2686 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
2687 @retval Others Other errors as indicated.\r
2688**/\r
2689EFI_STATUS\r
2690HddPasswordConfigFormInit (\r
2691 OUT HDD_PASSWORD_DXE_PRIVATE_DATA **Instance\r
2692 )\r
2693{\r
2694 EFI_STATUS Status;\r
2695 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
2696\r
2697 InitializeListHead (&mHddPasswordConfigFormList);\r
2698\r
2699 Private = AllocateZeroPool (sizeof (HDD_PASSWORD_DXE_PRIVATE_DATA));\r
2700 if (Private == NULL) {\r
2701 return EFI_OUT_OF_RESOURCES;\r
2702 }\r
2703\r
2704 Private->Signature = HDD_PASSWORD_DXE_PRIVATE_SIGNATURE;\r
2705\r
2706 Private->ConfigAccess.ExtractConfig = HddPasswordFormExtractConfig;\r
2707 Private->ConfigAccess.RouteConfig = HddPasswordFormRouteConfig;\r
2708 Private->ConfigAccess.Callback = HddPasswordFormCallback;\r
2709\r
2710 //\r
2711 // Install Device Path Protocol and Config Access protocol to driver handle\r
2712 //\r
2713 Status = gBS->InstallMultipleProtocolInterfaces (\r
2714 &Private->DriverHandle,\r
2715 &gEfiDevicePathProtocolGuid,\r
2716 &mHddPasswordHiiVendorDevicePath,\r
2717 &gEfiHiiConfigAccessProtocolGuid,\r
2718 &Private->ConfigAccess,\r
2719 NULL\r
2720 );\r
2721 ASSERT_EFI_ERROR (Status);\r
2722 if (EFI_ERROR (Status)) {\r
2723 FreePool(Private);\r
2724 return Status;\r
2725 }\r
2726\r
2727 //\r
2728 // Publish our HII data\r
2729 //\r
2730 Private->HiiHandle = HiiAddPackages (\r
2731 &mHddPasswordVendorGuid,\r
2732 Private->DriverHandle,\r
2733 HddPasswordDxeStrings,\r
2734 HddPasswordBin,\r
2735 NULL\r
2736 );\r
2737 if (Private->HiiHandle == NULL) {\r
2738 FreePool(Private);\r
2739 return EFI_OUT_OF_RESOURCES;\r
2740 }\r
2741\r
2742 *Instance = Private;\r
2743 return Status;\r
2744}\r
2745\r
2746/**\r
2747 Main entry for this driver.\r
2748\r
2749 @param ImageHandle Image handle this driver.\r
2750 @param SystemTable Pointer to SystemTable.\r
2751\r
2752 @retval EFI_SUCESS This function always complete successfully.\r
2753\r
2754**/\r
2755EFI_STATUS\r
2756EFIAPI\r
2757HddPasswordDxeInit (\r
2758 IN EFI_HANDLE ImageHandle,\r
2759 IN EFI_SYSTEM_TABLE *SystemTable\r
2760 )\r
2761{\r
2762 EFI_STATUS Status;\r
2763 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
2764 EFI_EVENT Registration;\r
2765 EFI_EVENT EndOfDxeEvent;\r
2766 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
2767\r
2768 Private = NULL;\r
2769\r
2770 //\r
2771 // Initialize the configuration form of HDD Password.\r
2772 //\r
2773 Status = HddPasswordConfigFormInit (&Private);\r
2774 if (EFI_ERROR (Status)) {\r
2775 return Status;\r
2776 }\r
2777\r
2778 //\r
2779 // Register HddPasswordNotificationEvent() notify function.\r
2780 //\r
2781 EfiCreateProtocolNotifyEvent (\r
2782 &gEfiAtaPassThruProtocolGuid,\r
2783 TPL_CALLBACK,\r
2784 HddPasswordNotificationEvent,\r
2785 (VOID *)Private,\r
2786 &Registration\r
2787 );\r
2788\r
2789 Status = gBS->CreateEventEx (\r
2790 EVT_NOTIFY_SIGNAL,\r
2791 TPL_CALLBACK,\r
2792 HddPasswordEndOfDxeEventNotify,\r
2793 NULL,\r
2794 &gEfiEndOfDxeEventGroupGuid,\r
2795 &EndOfDxeEvent\r
2796 );\r
2797 ASSERT_EFI_ERROR (Status);\r
2798\r
2799 //\r
2800 // Make HDD_PASSWORD_VARIABLE_NAME varible read-only.\r
2801 //\r
2802 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
2803 if (!EFI_ERROR (Status)) {\r
2804 Status = VariableLock->RequestToLock (\r
2805 VariableLock,\r
2806 HDD_PASSWORD_VARIABLE_NAME,\r
2807 &mHddPasswordVendorGuid\r
2808 );\r
2809 DEBUG ((DEBUG_INFO, "%a(): Lock %s variable (%r)\n", __FUNCTION__, HDD_PASSWORD_VARIABLE_NAME, Status));\r
2810 ASSERT_EFI_ERROR (Status);\r
2811 }\r
2812\r
2813 return Status;\r
2814}\r